diff options
author | Mike Buland <eichlan@xagasoft.com> | 2006-05-01 17:11:04 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2006-05-01 17:11:04 +0000 |
commit | f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54 (patch) | |
tree | 53cec4864776e07950e3c72f2a990a1017d08045 | |
download | libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.gz libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.bz2 libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.xz libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.zip |
libbu++ is finally laid out the way it should be, trunk, branches, and tags.
89 files changed, 24714 insertions, 0 deletions
diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..213c87b --- /dev/null +++ b/Doxyfile | |||
@@ -0,0 +1,275 @@ | |||
1 | # Doxyfile 1.4.1-KDevelop | ||
2 | |||
3 | #--------------------------------------------------------------------------- | ||
4 | # Project related configuration options | ||
5 | #--------------------------------------------------------------------------- | ||
6 | PROJECT_NAME = libbu++ | ||
7 | PROJECT_NUMBER = $VERSION$ | ||
8 | OUTPUT_DIRECTORY = api | ||
9 | CREATE_SUBDIRS = NO | ||
10 | OUTPUT_LANGUAGE = English | ||
11 | USE_WINDOWS_ENCODING = NO | ||
12 | BRIEF_MEMBER_DESC = YES | ||
13 | REPEAT_BRIEF = YES | ||
14 | ABBREVIATE_BRIEF = "The $name class" \ | ||
15 | "The $name widget" \ | ||
16 | "The $name file" \ | ||
17 | is \ | ||
18 | provides \ | ||
19 | specifies \ | ||
20 | contains \ | ||
21 | represents \ | ||
22 | a \ | ||
23 | an \ | ||
24 | the | ||
25 | ALWAYS_DETAILED_SEC = NO | ||
26 | INLINE_INHERITED_MEMB = NO | ||
27 | FULL_PATH_NAMES = NO | ||
28 | STRIP_FROM_PATH = /home/eichlan/projects/libbu++/ | ||
29 | STRIP_FROM_INC_PATH = | ||
30 | SHORT_NAMES = NO | ||
31 | JAVADOC_AUTOBRIEF = YES | ||
32 | MULTILINE_CPP_IS_BRIEF = NO | ||
33 | DETAILS_AT_TOP = NO | ||
34 | INHERIT_DOCS = YES | ||
35 | DISTRIBUTE_GROUP_DOC = NO | ||
36 | TAB_SIZE = 4 | ||
37 | ALIASES = | ||
38 | OPTIMIZE_OUTPUT_FOR_C = NO | ||
39 | OPTIMIZE_OUTPUT_JAVA = NO | ||
40 | SUBGROUPING = YES | ||
41 | #--------------------------------------------------------------------------- | ||
42 | # Build related configuration options | ||
43 | #--------------------------------------------------------------------------- | ||
44 | EXTRACT_ALL = YES | ||
45 | EXTRACT_PRIVATE = YES | ||
46 | EXTRACT_STATIC = YES | ||
47 | EXTRACT_LOCAL_CLASSES = YES | ||
48 | EXTRACT_LOCAL_METHODS = YES | ||
49 | HIDE_UNDOC_MEMBERS = NO | ||
50 | HIDE_UNDOC_CLASSES = NO | ||
51 | HIDE_FRIEND_COMPOUNDS = NO | ||
52 | HIDE_IN_BODY_DOCS = NO | ||
53 | INTERNAL_DOCS = YES | ||
54 | CASE_SENSE_NAMES = YES | ||
55 | HIDE_SCOPE_NAMES = NO | ||
56 | SHOW_INCLUDE_FILES = YES | ||
57 | INLINE_INFO = YES | ||
58 | SORT_MEMBER_DOCS = YES | ||
59 | SORT_BRIEF_DOCS = NO | ||
60 | SORT_BY_SCOPE_NAME = NO | ||
61 | GENERATE_TODOLIST = YES | ||
62 | GENERATE_TESTLIST = YES | ||
63 | GENERATE_BUGLIST = YES | ||
64 | GENERATE_DEPRECATEDLIST= YES | ||
65 | ENABLED_SECTIONS = | ||
66 | MAX_INITIALIZER_LINES = 30 | ||
67 | SHOW_USED_FILES = YES | ||
68 | SHOW_DIRECTORIES = YES | ||
69 | FILE_VERSION_FILTER = | ||
70 | #--------------------------------------------------------------------------- | ||
71 | # configuration options related to warning and progress messages | ||
72 | #--------------------------------------------------------------------------- | ||
73 | QUIET = NO | ||
74 | WARNINGS = YES | ||
75 | WARN_IF_UNDOCUMENTED = YES | ||
76 | WARN_IF_DOC_ERROR = YES | ||
77 | WARN_NO_PARAMDOC = NO | ||
78 | WARN_FORMAT = "$file:$line: $text" | ||
79 | WARN_LOGFILE = | ||
80 | #--------------------------------------------------------------------------- | ||
81 | # configuration options related to the input files | ||
82 | #--------------------------------------------------------------------------- | ||
83 | INPUT = . | ||
84 | FILE_PATTERNS = *.c \ | ||
85 | *.cc \ | ||
86 | *.cxx \ | ||
87 | *.cpp \ | ||
88 | *.c++ \ | ||
89 | *.java \ | ||
90 | *.ii \ | ||
91 | *.ixx \ | ||
92 | *.ipp \ | ||
93 | *.i++ \ | ||
94 | *.inl \ | ||
95 | *.h \ | ||
96 | *.hh \ | ||
97 | *.hxx \ | ||
98 | *.hpp \ | ||
99 | *.h++ \ | ||
100 | *.idl \ | ||
101 | *.odl \ | ||
102 | *.cs \ | ||
103 | *.php \ | ||
104 | *.php3 \ | ||
105 | *.inc \ | ||
106 | *.m \ | ||
107 | *.mm \ | ||
108 | *.dox \ | ||
109 | *.C \ | ||
110 | *.CC \ | ||
111 | *.C++ \ | ||
112 | *.II \ | ||
113 | *.I++ \ | ||
114 | *.H \ | ||
115 | *.HH \ | ||
116 | *.H++ \ | ||
117 | *.CS \ | ||
118 | *.PHP \ | ||
119 | *.PHP3 \ | ||
120 | *.M \ | ||
121 | *.MM \ | ||
122 | *.C \ | ||
123 | *.H \ | ||
124 | *.tlh \ | ||
125 | *.diff \ | ||
126 | *.patch \ | ||
127 | *.moc \ | ||
128 | *.xpm \ | ||
129 | *.dox | ||
130 | RECURSIVE = YES | ||
131 | EXCLUDE = | ||
132 | EXCLUDE_SYMLINKS = NO | ||
133 | EXCLUDE_PATTERNS = | ||
134 | EXAMPLE_PATH = | ||
135 | EXAMPLE_PATTERNS = * | ||
136 | EXAMPLE_RECURSIVE = NO | ||
137 | IMAGE_PATH = | ||
138 | INPUT_FILTER = | ||
139 | FILTER_PATTERNS = | ||
140 | FILTER_SOURCE_FILES = NO | ||
141 | #--------------------------------------------------------------------------- | ||
142 | # configuration options related to source browsing | ||
143 | #--------------------------------------------------------------------------- | ||
144 | SOURCE_BROWSER = YES | ||
145 | INLINE_SOURCES = NO | ||
146 | STRIP_CODE_COMMENTS = YES | ||
147 | REFERENCED_BY_RELATION = YES | ||
148 | REFERENCES_RELATION = YES | ||
149 | VERBATIM_HEADERS = YES | ||
150 | #--------------------------------------------------------------------------- | ||
151 | # configuration options related to the alphabetical class index | ||
152 | #--------------------------------------------------------------------------- | ||
153 | ALPHABETICAL_INDEX = YES | ||
154 | COLS_IN_ALPHA_INDEX = 5 | ||
155 | IGNORE_PREFIX = | ||
156 | #--------------------------------------------------------------------------- | ||
157 | # configuration options related to the HTML output | ||
158 | #--------------------------------------------------------------------------- | ||
159 | GENERATE_HTML = YES | ||
160 | HTML_OUTPUT = html | ||
161 | HTML_FILE_EXTENSION = .html | ||
162 | HTML_HEADER = | ||
163 | HTML_FOOTER = | ||
164 | HTML_STYLESHEET = | ||
165 | HTML_ALIGN_MEMBERS = YES | ||
166 | GENERATE_HTMLHELP = NO | ||
167 | CHM_FILE = | ||
168 | HHC_LOCATION = | ||
169 | GENERATE_CHI = NO | ||
170 | BINARY_TOC = NO | ||
171 | TOC_EXPAND = NO | ||
172 | DISABLE_INDEX = NO | ||
173 | ENUM_VALUES_PER_LINE = 4 | ||
174 | GENERATE_TREEVIEW = NO | ||
175 | TREEVIEW_WIDTH = 250 | ||
176 | #--------------------------------------------------------------------------- | ||
177 | # configuration options related to the LaTeX output | ||
178 | #--------------------------------------------------------------------------- | ||
179 | GENERATE_LATEX = YES | ||
180 | LATEX_OUTPUT = latex | ||
181 | LATEX_CMD_NAME = latex | ||
182 | MAKEINDEX_CMD_NAME = makeindex | ||
183 | COMPACT_LATEX = NO | ||
184 | PAPER_TYPE = letter | ||
185 | EXTRA_PACKAGES = | ||
186 | LATEX_HEADER = | ||
187 | PDF_HYPERLINKS = YES | ||
188 | USE_PDFLATEX = YES | ||
189 | LATEX_BATCHMODE = NO | ||
190 | LATEX_HIDE_INDICES = NO | ||
191 | #--------------------------------------------------------------------------- | ||
192 | # configuration options related to the RTF output | ||
193 | #--------------------------------------------------------------------------- | ||
194 | GENERATE_RTF = NO | ||
195 | RTF_OUTPUT = rtf | ||
196 | COMPACT_RTF = NO | ||
197 | RTF_HYPERLINKS = YES | ||
198 | RTF_STYLESHEET_FILE = | ||
199 | RTF_EXTENSIONS_FILE = | ||
200 | #--------------------------------------------------------------------------- | ||
201 | # configuration options related to the man page output | ||
202 | #--------------------------------------------------------------------------- | ||
203 | GENERATE_MAN = NO | ||
204 | MAN_OUTPUT = man | ||
205 | MAN_EXTENSION = .3 | ||
206 | MAN_LINKS = NO | ||
207 | #--------------------------------------------------------------------------- | ||
208 | # configuration options related to the XML output | ||
209 | #--------------------------------------------------------------------------- | ||
210 | GENERATE_XML = NO | ||
211 | XML_OUTPUT = xml | ||
212 | XML_SCHEMA = | ||
213 | XML_DTD = | ||
214 | XML_PROGRAMLISTING = YES | ||
215 | #--------------------------------------------------------------------------- | ||
216 | # configuration options for the AutoGen Definitions output | ||
217 | #--------------------------------------------------------------------------- | ||
218 | GENERATE_AUTOGEN_DEF = NO | ||
219 | #--------------------------------------------------------------------------- | ||
220 | # configuration options related to the Perl module output | ||
221 | #--------------------------------------------------------------------------- | ||
222 | GENERATE_PERLMOD = NO | ||
223 | PERLMOD_LATEX = YES | ||
224 | PERLMOD_PRETTY = YES | ||
225 | PERLMOD_MAKEVAR_PREFIX = | ||
226 | #--------------------------------------------------------------------------- | ||
227 | # Configuration options related to the preprocessor | ||
228 | #--------------------------------------------------------------------------- | ||
229 | ENABLE_PREPROCESSING = YES | ||
230 | MACRO_EXPANSION = YES | ||
231 | EXPAND_ONLY_PREDEF = NO | ||
232 | SEARCH_INCLUDES = YES | ||
233 | INCLUDE_PATH = | ||
234 | INCLUDE_FILE_PATTERNS = | ||
235 | PREDEFINED = | ||
236 | EXPAND_AS_DEFINED = | ||
237 | SKIP_FUNCTION_MACROS = YES | ||
238 | #--------------------------------------------------------------------------- | ||
239 | # Configuration::additions related to external references | ||
240 | #--------------------------------------------------------------------------- | ||
241 | TAGFILES = | ||
242 | GENERATE_TAGFILE = | ||
243 | ALLEXTERNALS = NO | ||
244 | EXTERNAL_GROUPS = YES | ||
245 | PERL_PATH = /usr/bin/perl | ||
246 | #--------------------------------------------------------------------------- | ||
247 | # Configuration options related to the dot tool | ||
248 | #--------------------------------------------------------------------------- | ||
249 | CLASS_DIAGRAMS = YES | ||
250 | HIDE_UNDOC_RELATIONS = YES | ||
251 | HAVE_DOT = YES | ||
252 | CLASS_GRAPH = YES | ||
253 | COLLABORATION_GRAPH = YES | ||
254 | GROUP_GRAPHS = YES | ||
255 | UML_LOOK = NO | ||
256 | TEMPLATE_RELATIONS = NO | ||
257 | INCLUDE_GRAPH = YES | ||
258 | INCLUDED_BY_GRAPH = YES | ||
259 | CALL_GRAPH = NO | ||
260 | GRAPHICAL_HIERARCHY = YES | ||
261 | DIRECTORY_GRAPH = YES | ||
262 | DOT_IMAGE_FORMAT = png | ||
263 | DOT_PATH = | ||
264 | DOTFILE_DIRS = | ||
265 | MAX_DOT_GRAPH_WIDTH = 1024 | ||
266 | MAX_DOT_GRAPH_HEIGHT = 1024 | ||
267 | MAX_DOT_GRAPH_DEPTH = 1000 | ||
268 | DOT_TRANSPARENT = NO | ||
269 | DOT_MULTI_TARGETS = NO | ||
270 | GENERATE_LEGEND = YES | ||
271 | DOT_CLEANUP = YES | ||
272 | #--------------------------------------------------------------------------- | ||
273 | # Configuration::additions related to the search engine | ||
274 | #--------------------------------------------------------------------------- | ||
275 | SEARCHENGINE = NO | ||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b3d213d --- /dev/null +++ b/Makefile | |||
@@ -0,0 +1,69 @@ | |||
1 | OBJS:=$(patsubst %.cpp,%.o,$(wildcard src/*.cpp)) | ||
2 | TOBJS:=$(patsubst %.cpp,%.o,$(wildcard src/test/*.cpp)) | ||
3 | TDIRS:=$(filter-out %.o %.cpp %.h %.d,$(wildcard src/test/*)) | ||
4 | TESTS:=$(patsubst src/test/%.o,%,$(TOBJS)) $(patsubst src/test/%,%,$(TDIRS)) | ||
5 | ATOBJS:=$(TOBJS) $(patsubst %.cpp,%.o,$(foreach dr,$(TDIRS),$(wildcard $(dr)/*.cpp))) | ||
6 | LIB:=libbu++.a | ||
7 | DATE:=$(shell date +%F) | ||
8 | |||
9 | TXTCPP:="\ g++:\ \ \ " | ||
10 | TXTLNK:="\ \ ld:\ \ \ " | ||
11 | TXTDEP:="\ dep:\ \ \ " | ||
12 | TXTARC:="\ \ ar:\ \ \ " | ||
13 | |||
14 | .PHONY: all clean dist tests depclean cleanapi | ||
15 | .SILENT: clean $(OBJS) $(TOBJS) $(ATOBJS) $(TESTS) $(patsubst %.o,%.d,$(OBJS) $(TOBJS) $(ATOBJS) $(TESTS)) $(LIB) | ||
16 | |||
17 | all: libbu++.a tests | ||
18 | |||
19 | depclean: | ||
20 | -rm $(patsubst %.o,%.d,$(OBJS) $(ATOBJS)) | ||
21 | |||
22 | -include $(patsubst %.o,%.d,$(OBJS) $(ATOBJS)) | ||
23 | |||
24 | clean: | ||
25 | -rm $(OBJS) $(ATOBJS) $(TESTS) $(LIB) | ||
26 | |||
27 | # This bit I cribbed from the docs, seems to work great though! | ||
28 | %.d: %.cpp | ||
29 | g++ $(CXXFLAGS) -Isrc -M $(CPPFLAGS) $< | sed 's,\($(notdir $*)\)\.o[: ]*,$(dir $*)\1.o $@: ,g' > $@ | ||
30 | echo "$(TXTDEP)$@" | ||
31 | |||
32 | %.o: %.cpp | ||
33 | g++ $(CXXFLAGS) -Isrc $(foreach dr,$(filter $(dir $@),$(foreach ddr,$(TDIRS),$(ddr)/)),-I$(dr)) -ggdb -c -o $@ $< | ||
34 | echo "$(TXTCPP)$@" | ||
35 | |||
36 | $(LIB): $(OBJS) | ||
37 | ar cr $(LIB) $(OBJS) | ||
38 | echo "$(TXTARC)$@" | ||
39 | |||
40 | $(TESTS): $(ATOBJS) $(LIB) | ||
41 | g++ $(LDFLAGS) -ggdb $(filter %$@.o, $(TOBJS) ) $(patsubst %.cpp,%.o,$(wildcard $(filter %$@, $(TDIRS))/*.cpp)) -L. -lbu++ -o $@ | ||
42 | echo "$(TXTLNK)$@" | ||
43 | |||
44 | tests: $(TESTS) | ||
45 | |||
46 | dist: clean depclean | ||
47 | mkdir libbu++-$(DATE) | ||
48 | cp -a --target-directory=libbu++-$(DATE) Makefile src | ||
49 | tar --exclude=\.svn -c libbu++-$(DATE) | bzip2 -9 > libbu++-$(DATE).tar.bz2 | ||
50 | rm -Rf libbu++-$(DATE) | ||
51 | |||
52 | install: libbu++.a | ||
53 | cat src/*.h | grep -v "#include \"" - > libbu++.h | ||
54 | cp -a libbu++.a $(PREFIX)/lib | ||
55 | cp -a libbu++.h $(PREFIX)/include | ||
56 | |||
57 | cleanapi: | ||
58 | -rm -Rf api | ||
59 | |||
60 | api: $(SRC) | ||
61 | -rm -Rf api | ||
62 | doxygen | ||
63 | make -C api/latex | ||
64 | |||
65 | #tests: $(TOBJS) $(LIB) | ||
66 | # for file in $(patsubst src/test/%.o,%,$(TOBJS)); \ | ||
67 | # do g++ -o $$file src/test/$$file.o -L. -lbu++; \ | ||
68 | # done | ||
69 | |||
diff --git a/misc/rfc2060-imap.txt b/misc/rfc2060-imap.txt new file mode 100644 index 0000000..cf46159 --- /dev/null +++ b/misc/rfc2060-imap.txt | |||
@@ -0,0 +1,4595 @@ | |||
1 | |||
2 | |||
3 | |||
4 | |||
5 | |||
6 | |||
7 | Network Working Group M. Crispin | ||
8 | Request for Comments: 2060 University of Washington | ||
9 | Obsoletes: 1730 December 1996 | ||
10 | Category: Standards Track | ||
11 | |||
12 | |||
13 | INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 | ||
14 | |||
15 | Status of this Memo | ||
16 | |||
17 | This document specifies an Internet standards track protocol for the | ||
18 | Internet community, and requests discussion and suggestions for | ||
19 | improvements. Please refer to the current edition of the "Internet | ||
20 | Official Protocol Standards" (STD 1) for the standardization state | ||
21 | and status of this protocol. Distribution of this memo is unlimited. | ||
22 | |||
23 | Abstract | ||
24 | |||
25 | The Internet Message Access Protocol, Version 4rev1 (IMAP4rev1) | ||
26 | allows a client to access and manipulate electronic mail messages on | ||
27 | a server. IMAP4rev1 permits manipulation of remote message folders, | ||
28 | called "mailboxes", in a way that is functionally equivalent to local | ||
29 | mailboxes. IMAP4rev1 also provides the capability for an offline | ||
30 | client to resynchronize with the server (see also [IMAP-DISC]). | ||
31 | |||
32 | IMAP4rev1 includes operations for creating, deleting, and renaming | ||
33 | mailboxes; checking for new messages; permanently removing messages; | ||
34 | setting and clearing flags; [RFC-822] and [MIME-IMB] parsing; | ||
35 | searching; and selective fetching of message attributes, texts, and | ||
36 | portions thereof. Messages in IMAP4rev1 are accessed by the use of | ||
37 | numbers. These numbers are either message sequence numbers or unique | ||
38 | identifiers. | ||
39 | |||
40 | IMAP4rev1 supports a single server. A mechanism for accessing | ||
41 | configuration information to support multiple IMAP4rev1 servers is | ||
42 | discussed in [ACAP]. | ||
43 | |||
44 | IMAP4rev1 does not specify a means of posting mail; this function is | ||
45 | handled by a mail transfer protocol such as [SMTP]. | ||
46 | |||
47 | IMAP4rev1 is designed to be upwards compatible from the [IMAP2] and | ||
48 | unpublished IMAP2bis protocols. In the course of the evolution of | ||
49 | IMAP4rev1, some aspects in the earlier protocol have become obsolete. | ||
50 | Obsolete commands, responses, and data formats which an IMAP4rev1 | ||
51 | implementation may encounter when used with an earlier implementation | ||
52 | are described in [IMAP-OBSOLETE]. | ||
53 | |||
54 | |||
55 | |||
56 | |||
57 | |||
58 | Crispin Standards Track [Page 1] | ||
59 | |||
60 | RFC 2060 IMAP4rev1 December 1996 | ||
61 | |||
62 | |||
63 | Other compatibility issues with IMAP2bis, the most common variant of | ||
64 | the earlier protocol, are discussed in [IMAP-COMPAT]. A full | ||
65 | discussion of compatibility issues with rare (and presumed extinct) | ||
66 | variants of [IMAP2] is in [IMAP-HISTORICAL]; this document is | ||
67 | primarily of historical interest. | ||
68 | |||
69 | Table of Contents | ||
70 | |||
71 | IMAP4rev1 Protocol Specification .................................. 4 | ||
72 | 1. How to Read This Document ................................. 4 | ||
73 | 1.1. Organization of This Document ............................. 4 | ||
74 | 1.2. Conventions Used in This Document ......................... 4 | ||
75 | 2. Protocol Overview ......................................... 5 | ||
76 | 2.1. Link Level ................................................ 5 | ||
77 | 2.2. Commands and Responses .................................... 6 | ||
78 | 2.2.1. Client Protocol Sender and Server Protocol Receiver ....... 6 | ||
79 | 2.2.2. Server Protocol Sender and Client Protocol Receiver ....... 7 | ||
80 | 2.3. Message Attributes ........................................ 7 | ||
81 | 2.3.1. Message Numbers ........................................... 7 | ||
82 | 2.3.1.1. Unique Identifier (UID) Message Attribute ......... 7 | ||
83 | 2.3.1.2. Message Sequence Number Message Attribute ......... 9 | ||
84 | 2.3.2. Flags Message Attribute .................................... 9 | ||
85 | 2.3.3. Internal Date Message Attribute ........................... 10 | ||
86 | 2.3.4. [RFC-822] Size Message Attribute .......................... 11 | ||
87 | 2.3.5. Envelope Structure Message Attribute ...................... 11 | ||
88 | 2.3.6. Body Structure Message Attribute .......................... 11 | ||
89 | 2.4. Message Texts ............................................. 11 | ||
90 | 3. State and Flow Diagram .................................... 11 | ||
91 | 3.1. Non-Authenticated State ................................... 11 | ||
92 | 3.2. Authenticated State ....................................... 11 | ||
93 | 3.3. Selected State ............................................ 12 | ||
94 | 3.4. Logout State .............................................. 12 | ||
95 | 4. Data Formats .............................................. 12 | ||
96 | 4.1. Atom ...................................................... 13 | ||
97 | 4.2. Number .................................................... 13 | ||
98 | 4.3. String ..................................................... 13 | ||
99 | 4.3.1. 8-bit and Binary Strings .................................. 13 | ||
100 | 4.4. Parenthesized List ........................................ 14 | ||
101 | 4.5. NIL ....................................................... 14 | ||
102 | 5. Operational Considerations ................................ 14 | ||
103 | 5.1. Mailbox Naming ............................................ 14 | ||
104 | 5.1.1. Mailbox Hierarchy Naming .................................. 14 | ||
105 | 5.1.2. Mailbox Namespace Naming Convention ....................... 14 | ||
106 | 5.1.3. Mailbox International Naming Convention ................... 15 | ||
107 | 5.2. Mailbox Size and Message Status Updates ................... 16 | ||
108 | 5.3. Response when no Command in Progress ...................... 16 | ||
109 | 5.4. Autologout Timer .......................................... 16 | ||
110 | 5.5. Multiple Commands in Progress ............................. 17 | ||
111 | |||
112 | |||
113 | |||
114 | Crispin Standards Track [Page 2] | ||
115 | |||
116 | RFC 2060 IMAP4rev1 December 1996 | ||
117 | |||
118 | |||
119 | 6. Client Commands ........................................... 17 | ||
120 | 6.1. Client Commands - Any State ............................... 18 | ||
121 | 6.1.1. CAPABILITY Command ........................................ 18 | ||
122 | 6.1.2. NOOP Command .............................................. 19 | ||
123 | 6.1.3. LOGOUT Command ............................................ 20 | ||
124 | 6.2. Client Commands - Non-Authenticated State ................. 20 | ||
125 | 6.2.1. AUTHENTICATE Command ...................................... 21 | ||
126 | 6.2.2. LOGIN Command ............................................. 22 | ||
127 | 6.3. Client Commands - Authenticated State ..................... 22 | ||
128 | 6.3.1. SELECT Command ............................................ 23 | ||
129 | 6.3.2. EXAMINE Command ........................................... 24 | ||
130 | 6.3.3. CREATE Command ............................................ 25 | ||
131 | 6.3.4. DELETE Command ............................................ 26 | ||
132 | 6.3.5. RENAME Command ............................................ 27 | ||
133 | 6.3.6. SUBSCRIBE Command ......................................... 29 | ||
134 | 6.3.7. UNSUBSCRIBE Command ....................................... 30 | ||
135 | 6.3.8. LIST Command .............................................. 30 | ||
136 | 6.3.9. LSUB Command .............................................. 32 | ||
137 | 6.3.10. STATUS Command ............................................ 33 | ||
138 | 6.3.11. APPEND Command ............................................ 34 | ||
139 | 6.4. Client Commands - Selected State .......................... 35 | ||
140 | 6.4.1. CHECK Command ............................................. 36 | ||
141 | 6.4.2. CLOSE Command ............................................. 36 | ||
142 | 6.4.3. EXPUNGE Command ........................................... 37 | ||
143 | 6.4.4. SEARCH Command ............................................ 37 | ||
144 | 6.4.5. FETCH Command ............................................. 41 | ||
145 | 6.4.6. STORE Command ............................................. 45 | ||
146 | 6.4.7. COPY Command .............................................. 46 | ||
147 | 6.4.8. UID Command ............................................... 47 | ||
148 | 6.5. Client Commands - Experimental/Expansion .................. 48 | ||
149 | 6.5.1. X<atom> Command ........................................... 48 | ||
150 | 7. Server Responses .......................................... 48 | ||
151 | 7.1. Server Responses - Status Responses ....................... 49 | ||
152 | 7.1.1. OK Response ............................................... 51 | ||
153 | 7.1.2. NO Response ............................................... 51 | ||
154 | 7.1.3. BAD Response .............................................. 52 | ||
155 | 7.1.4. PREAUTH Response .......................................... 52 | ||
156 | 7.1.5. BYE Response .............................................. 52 | ||
157 | 7.2. Server Responses - Server and Mailbox Status .............. 53 | ||
158 | 7.2.1. CAPABILITY Response ....................................... 53 | ||
159 | 7.2.2. LIST Response .............................................. 54 | ||
160 | 7.2.3. LSUB Response ............................................. 55 | ||
161 | 7.2.4 STATUS Response ........................................... 55 | ||
162 | 7.2.5. SEARCH Response ........................................... 55 | ||
163 | 7.2.6. FLAGS Response ............................................ 56 | ||
164 | 7.3. Server Responses - Mailbox Size ........................... 56 | ||
165 | 7.3.1. EXISTS Response ........................................... 56 | ||
166 | 7.3.2. RECENT Response ........................................... 57 | ||
167 | |||
168 | |||
169 | |||
170 | Crispin Standards Track [Page 3] | ||
171 | |||
172 | RFC 2060 IMAP4rev1 December 1996 | ||
173 | |||
174 | |||
175 | 7.4. Server Responses - Message Status ......................... 57 | ||
176 | 7.4.1. EXPUNGE Response .......................................... 57 | ||
177 | 7.4.2. FETCH Response ............................................ 58 | ||
178 | 7.5. Server Responses - Command Continuation Request ........... 63 | ||
179 | 8. Sample IMAP4rev1 connection ............................... 63 | ||
180 | 9. Formal Syntax ............................................. 64 | ||
181 | 10. Author's Note ............................................. 74 | ||
182 | 11. Security Considerations ................................... 74 | ||
183 | 12. Author's Address .......................................... 75 | ||
184 | Appendices ........................................................ 76 | ||
185 | A. References ................................................ 76 | ||
186 | B. Changes from RFC 1730 ..................................... 77 | ||
187 | C. Key Word Index ............................................ 79 | ||
188 | |||
189 | |||
190 | IMAP4rev1 Protocol Specification | ||
191 | |||
192 | 1. How to Read This Document | ||
193 | |||
194 | 1.1. Organization of This Document | ||
195 | |||
196 | This document is written from the point of view of the implementor of | ||
197 | an IMAP4rev1 client or server. Beyond the protocol overview in | ||
198 | section 2, it is not optimized for someone trying to understand the | ||
199 | operation of the protocol. The material in sections 3 through 5 | ||
200 | provides the general context and definitions with which IMAP4rev1 | ||
201 | operates. | ||
202 | |||
203 | Sections 6, 7, and 9 describe the IMAP commands, responses, and | ||
204 | syntax, respectively. The relationships among these are such that it | ||
205 | is almost impossible to understand any of them separately. In | ||
206 | particular, do not attempt to deduce command syntax from the command | ||
207 | section alone; instead refer to the Formal Syntax section. | ||
208 | |||
209 | 1.2. Conventions Used in This Document | ||
210 | |||
211 | In examples, "C:" and "S:" indicate lines sent by the client and | ||
212 | server respectively. | ||
213 | |||
214 | The following terms are used in this document to signify the | ||
215 | requirements of this specification. | ||
216 | |||
217 | 1) MUST, or the adjective REQUIRED, means that the definition is | ||
218 | an absolute requirement of the specification. | ||
219 | |||
220 | 2) MUST NOT that the definition is an absolute prohibition of the | ||
221 | specification. | ||
222 | |||
223 | |||
224 | |||
225 | |||
226 | Crispin Standards Track [Page 4] | ||
227 | |||
228 | RFC 2060 IMAP4rev1 December 1996 | ||
229 | |||
230 | |||
231 | 3) SHOULD means that there may exist valid reasons in particular | ||
232 | circumstances to ignore a particular item, but the full | ||
233 | implications MUST be understood and carefully weighed before | ||
234 | choosing a different course. | ||
235 | |||
236 | 4) SHOULD NOT means that there may exist valid reasons in | ||
237 | particular circumstances when the particular behavior is | ||
238 | acceptable or even useful, but the full implications SHOULD be | ||
239 | understood and the case carefully weighed before implementing | ||
240 | any behavior described with this label. | ||
241 | |||
242 | 5) MAY, or the adjective OPTIONAL, means that an item is truly | ||
243 | optional. One vendor may choose to include the item because a | ||
244 | particular marketplace requires it or because the vendor feels | ||
245 | that it enhances the product while another vendor may omit the | ||
246 | same item. An implementation which does not include a | ||
247 | particular option MUST be prepared to interoperate with another | ||
248 | implementation which does include the option. | ||
249 | |||
250 | "Can" is used instead of "may" when referring to a possible | ||
251 | circumstance or situation, as opposed to an optional facility of | ||
252 | the protocol. | ||
253 | |||
254 | "User" is used to refer to a human user, whereas "client" refers | ||
255 | to the software being run by the user. | ||
256 | |||
257 | "Connection" refers to the entire sequence of client/server | ||
258 | interaction from the initial establishment of the network | ||
259 | connection until its termination. "Session" refers to the | ||
260 | sequence of client/server interaction from the time that a mailbox | ||
261 | is selected (SELECT or EXAMINE command) until the time that | ||
262 | selection ends (SELECT or EXAMINE of another mailbox, CLOSE | ||
263 | command, or connection termination). | ||
264 | |||
265 | Characters are 7-bit US-ASCII unless otherwise specified. Other | ||
266 | character sets are indicated using a "CHARSET", as described in | ||
267 | [MIME-IMT] and defined in [CHARSET]. CHARSETs have important | ||
268 | additional semantics in addition to defining character set; refer | ||
269 | to these documents for more detail. | ||
270 | |||
271 | 2. Protocol Overview | ||
272 | |||
273 | 2.1. Link Level | ||
274 | |||
275 | The IMAP4rev1 protocol assumes a reliable data stream such as | ||
276 | provided by TCP. When TCP is used, an IMAP4rev1 server listens on | ||
277 | port 143. | ||
278 | |||
279 | |||
280 | |||
281 | |||
282 | Crispin Standards Track [Page 5] | ||
283 | |||
284 | RFC 2060 IMAP4rev1 December 1996 | ||
285 | |||
286 | |||
287 | 2.2. Commands and Responses | ||
288 | |||
289 | An IMAP4rev1 connection consists of the establishment of a | ||
290 | client/server network connection, an initial greeting from the | ||
291 | server, and client/server interactions. These client/server | ||
292 | interactions consist of a client command, server data, and a server | ||
293 | completion result response. | ||
294 | |||
295 | All interactions transmitted by client and server are in the form of | ||
296 | lines; that is, strings that end with a CRLF. The protocol receiver | ||
297 | of an IMAP4rev1 client or server is either reading a line, or is | ||
298 | reading a sequence of octets with a known count followed by a line. | ||
299 | |||
300 | 2.2.1. Client Protocol Sender and Server Protocol Receiver | ||
301 | |||
302 | The client command begins an operation. Each client command is | ||
303 | prefixed with an identifier (typically a short alphanumeric string, | ||
304 | e.g. A0001, A0002, etc.) called a "tag". A different tag is | ||
305 | generated by the client for each command. | ||
306 | |||
307 | There are two cases in which a line from the client does not | ||
308 | represent a complete command. In one case, a command argument is | ||
309 | quoted with an octet count (see the description of literal in String | ||
310 | under Data Formats); in the other case, the command arguments require | ||
311 | server feedback (see the AUTHENTICATE command). In either case, the | ||
312 | server sends a command continuation request response if it is ready | ||
313 | for the octets (if appropriate) and the remainder of the command. | ||
314 | This response is prefixed with the token "+". | ||
315 | |||
316 | Note: If, instead, the server detected an error in the command, it | ||
317 | sends a BAD completion response with tag matching the command (as | ||
318 | described below) to reject the command and prevent the client from | ||
319 | sending any more of the command. | ||
320 | |||
321 | It is also possible for the server to send a completion response | ||
322 | for some other command (if multiple commands are in progress), or | ||
323 | untagged data. In either case, the command continuation request | ||
324 | is still pending; the client takes the appropriate action for the | ||
325 | response, and reads another response from the server. In all | ||
326 | cases, the client MUST send a complete command (including | ||
327 | receiving all command continuation request responses and command | ||
328 | continuations for the command) before initiating a new command. | ||
329 | |||
330 | The protocol receiver of an IMAP4rev1 server reads a command line | ||
331 | from the client, parses the command and its arguments, and transmits | ||
332 | server data and a server command completion result response. | ||
333 | |||
334 | |||
335 | |||
336 | |||
337 | |||
338 | Crispin Standards Track [Page 6] | ||
339 | |||
340 | RFC 2060 IMAP4rev1 December 1996 | ||
341 | |||
342 | |||
343 | 2.2.2. Server Protocol Sender and Client Protocol Receiver | ||
344 | |||
345 | Data transmitted by the server to the client and status responses | ||
346 | that do not indicate command completion are prefixed with the token | ||
347 | "*", and are called untagged responses. | ||
348 | |||
349 | Server data MAY be sent as a result of a client command, or MAY be | ||
350 | sent unilaterally by the server. There is no syntactic difference | ||
351 | between server data that resulted from a specific command and server | ||
352 | data that were sent unilaterally. | ||
353 | |||
354 | The server completion result response indicates the success or | ||
355 | failure of the operation. It is tagged with the same tag as the | ||
356 | client command which began the operation. Thus, if more than one | ||
357 | command is in progress, the tag in a server completion response | ||
358 | identifies the command to which the response applies. There are | ||
359 | three possible server completion responses: OK (indicating success), | ||
360 | NO (indicating failure), or BAD (indicating protocol error such as | ||
361 | unrecognized command or command syntax error). | ||
362 | |||
363 | The protocol receiver of an IMAP4rev1 client reads a response line | ||
364 | from the server. It then takes action on the response based upon the | ||
365 | first token of the response, which can be a tag, a "*", or a "+". | ||
366 | |||
367 | A client MUST be prepared to accept any server response at all times. | ||
368 | This includes server data that was not requested. Server data SHOULD | ||
369 | be recorded, so that the client can reference its recorded copy | ||
370 | rather than sending a command to the server to request the data. In | ||
371 | the case of certain server data, the data MUST be recorded. | ||
372 | |||
373 | This topic is discussed in greater detail in the Server Responses | ||
374 | section. | ||
375 | |||
376 | 2.3. Message Attributes | ||
377 | |||
378 | In addition to message text, each message has several attributes | ||
379 | associated with it. These attributes may be retrieved individually | ||
380 | or in conjunction with other attributes or message texts. | ||
381 | |||
382 | 2.3.1. Message Numbers | ||
383 | |||
384 | Messages in IMAP4rev1 are accessed by one of two numbers; the unique | ||
385 | identifier and the message sequence number. | ||
386 | |||
387 | 2.3.1.1. Unique Identifier (UID) Message Attribute | ||
388 | |||
389 | A 32-bit value assigned to each message, which when used with the | ||
390 | unique identifier validity value (see below) forms a 64-bit value | ||
391 | |||
392 | |||
393 | |||
394 | Crispin Standards Track [Page 7] | ||
395 | |||
396 | RFC 2060 IMAP4rev1 December 1996 | ||
397 | |||
398 | |||
399 | that is permanently guaranteed not to refer to any other message in | ||
400 | the mailbox. Unique identifiers are assigned in a strictly ascending | ||
401 | fashion in the mailbox; as each message is added to the mailbox it is | ||
402 | assigned a higher UID than the message(s) which were added | ||
403 | previously. | ||
404 | |||
405 | Unlike message sequence numbers, unique identifiers are not | ||
406 | necessarily contiguous. Unique identifiers also persist across | ||
407 | sessions. This permits a client to resynchronize its state from a | ||
408 | previous session with the server (e.g. disconnected or offline access | ||
409 | clients); this is discussed further in [IMAP-DISC]. | ||
410 | |||
411 | Associated with every mailbox is a unique identifier validity value, | ||
412 | which is sent in an UIDVALIDITY response code in an OK untagged | ||
413 | response at mailbox selection time. If unique identifiers from an | ||
414 | earlier session fail to persist to this session, the unique | ||
415 | identifier validity value MUST be greater than the one used in the | ||
416 | earlier session. | ||
417 | |||
418 | Note: Unique identifiers MUST be strictly ascending in the mailbox | ||
419 | at all times. If the physical message store is re-ordered by a | ||
420 | non-IMAP agent, this requires that the unique identifiers in the | ||
421 | mailbox be regenerated, since the former unique identifers are no | ||
422 | longer strictly ascending as a result of the re-ordering. Another | ||
423 | instance in which unique identifiers are regenerated is if the | ||
424 | message store has no mechanism to store unique identifiers. | ||
425 | Although this specification recognizes that this may be | ||
426 | unavoidable in certain server environments, it STRONGLY ENCOURAGES | ||
427 | message store implementation techniques that avoid this problem. | ||
428 | |||
429 | Another cause of non-persistance is if the mailbox is deleted and | ||
430 | a new mailbox with the same name is created at a later date, Since | ||
431 | the name is the same, a client may not know that this is a new | ||
432 | mailbox unless the unique identifier validity is different. A | ||
433 | good value to use for the unique identifier validity value is a | ||
434 | 32-bit representation of the creation date/time of the mailbox. | ||
435 | It is alright to use a constant such as 1, but only if it | ||
436 | guaranteed that unique identifiers will never be reused, even in | ||
437 | the case of a mailbox being deleted (or renamed) and a new mailbox | ||
438 | by the same name created at some future time. | ||
439 | |||
440 | The unique identifier of a message MUST NOT change during the | ||
441 | session, and SHOULD NOT change between sessions. However, if it is | ||
442 | not possible to preserve the unique identifier of a message in a | ||
443 | subsequent session, each subsequent session MUST have a new unique | ||
444 | identifier validity value that is larger than any that was used | ||
445 | previously. | ||
446 | |||
447 | |||
448 | |||
449 | |||
450 | Crispin Standards Track [Page 8] | ||
451 | |||
452 | RFC 2060 IMAP4rev1 December 1996 | ||
453 | |||
454 | |||
455 | 2.3.1.2. Message Sequence Number Message Attribute | ||
456 | |||
457 | A relative position from 1 to the number of messages in the mailbox. | ||
458 | This position MUST be ordered by ascending unique identifier. As | ||
459 | each new message is added, it is assigned a message sequence number | ||
460 | that is 1 higher than the number of messages in the mailbox before | ||
461 | that new message was added. | ||
462 | |||
463 | Message sequence numbers can be reassigned during the session. For | ||
464 | example, when a message is permanently removed (expunged) from the | ||
465 | mailbox, the message sequence number for all subsequent messages is | ||
466 | decremented. Similarly, a new message can be assigned a message | ||
467 | sequence number that was once held by some other message prior to an | ||
468 | expunge. | ||
469 | |||
470 | In addition to accessing messages by relative position in the | ||
471 | mailbox, message sequence numbers can be used in mathematical | ||
472 | calculations. For example, if an untagged "EXISTS 11" is received, | ||
473 | and previously an untagged "8 EXISTS" was received, three new | ||
474 | messages have arrived with message sequence numbers of 9, 10, and 11. | ||
475 | Another example; if message 287 in a 523 message mailbox has UID | ||
476 | 12345, there are exactly 286 messages which have lesser UIDs and 236 | ||
477 | messages which have greater UIDs. | ||
478 | |||
479 | 2.3.2. Flags Message Attribute | ||
480 | |||
481 | A list of zero or more named tokens associated with the message. A | ||
482 | flag is set by its addition to this list, and is cleared by its | ||
483 | removal. There are two types of flags in IMAP4rev1. A flag of | ||
484 | either type may be permanent or session-only. | ||
485 | |||
486 | A system flag is a flag name that is pre-defined in this | ||
487 | specification. All system flags begin with "\". Certain system | ||
488 | flags (\Deleted and \Seen) have special semantics described | ||
489 | elsewhere. The currently-defined system flags are: | ||
490 | |||
491 | \Seen Message has been read | ||
492 | |||
493 | \Answered Message has been answered | ||
494 | |||
495 | \Flagged Message is "flagged" for urgent/special attention | ||
496 | |||
497 | \Deleted Message is "deleted" for removal by later EXPUNGE | ||
498 | |||
499 | \Draft Message has not completed composition (marked as a | ||
500 | draft). | ||
501 | |||
502 | |||
503 | |||
504 | |||
505 | |||
506 | Crispin Standards Track [Page 9] | ||
507 | |||
508 | RFC 2060 IMAP4rev1 December 1996 | ||
509 | |||
510 | |||
511 | \Recent Message is "recently" arrived in this mailbox. This | ||
512 | session is the first session to have been notified | ||
513 | about this message; subsequent sessions will not see | ||
514 | \Recent set for this message. This flag can not be | ||
515 | altered by the client. | ||
516 | |||
517 | If it is not possible to determine whether or not | ||
518 | this session is the first session to be notified | ||
519 | about a message, then that message SHOULD be | ||
520 | considered recent. | ||
521 | |||
522 | If multiple connections have the same mailbox | ||
523 | selected simultaneously, it is undefined which of | ||
524 | these connections will see newly-arrives messages | ||
525 | with \Recent set and which will see it without | ||
526 | \Recent set. | ||
527 | |||
528 | A keyword is defined by the server implementation. Keywords do | ||
529 | not begin with "\". Servers MAY permit the client to define new | ||
530 | keywords in the mailbox (see the description of the | ||
531 | PERMANENTFLAGS response code for more information). | ||
532 | |||
533 | A flag may be permanent or session-only on a per-flag basis. | ||
534 | Permanent flags are those which the client can add or remove | ||
535 | from the message flags permanently; that is, subsequent sessions | ||
536 | will see any change in permanent flags. Changes to session | ||
537 | flags are valid only in that session. | ||
538 | |||
539 | Note: The \Recent system flag is a special case of a | ||
540 | session flag. \Recent can not be used as an argument in a | ||
541 | STORE command, and thus can not be changed at all. | ||
542 | |||
543 | 2.3.3. Internal Date Message Attribute | ||
544 | |||
545 | The internal date and time of the message on the server. This is not | ||
546 | the date and time in the [RFC-822] header, but rather a date and time | ||
547 | which reflects when the message was received. In the case of | ||
548 | messages delivered via [SMTP], this SHOULD be the date and time of | ||
549 | final delivery of the message as defined by [SMTP]. In the case of | ||
550 | messages delivered by the IMAP4rev1 COPY command, this SHOULD be the | ||
551 | internal date and time of the source message. In the case of | ||
552 | messages delivered by the IMAP4rev1 APPEND command, this SHOULD be | ||
553 | the date and time as specified in the APPEND command description. | ||
554 | All other cases are implementation defined. | ||
555 | |||
556 | |||
557 | |||
558 | |||
559 | |||
560 | |||
561 | |||
562 | Crispin Standards Track [Page 10] | ||
563 | |||
564 | RFC 2060 IMAP4rev1 December 1996 | ||
565 | |||
566 | |||
567 | 2.3.4. [RFC-822] Size Message Attribute | ||
568 | |||
569 | The number of octets in the message, as expressed in [RFC-822] | ||
570 | format. | ||
571 | |||
572 | 2.3.5. Envelope Structure Message Attribute | ||
573 | |||
574 | A parsed representation of the [RFC-822] envelope information (not to | ||
575 | be confused with an [SMTP] envelope) of the message. | ||
576 | |||
577 | 2.3.6. Body Structure Message Attribute | ||
578 | |||
579 | A parsed representation of the [MIME-IMB] body structure information | ||
580 | of the message. | ||
581 | |||
582 | 2.4. Message Texts | ||
583 | |||
584 | In addition to being able to fetch the full [RFC-822] text of a | ||
585 | message, IMAP4rev1 permits the fetching of portions of the full | ||
586 | message text. Specifically, it is possible to fetch the [RFC-822] | ||
587 | message header, [RFC-822] message body, a [MIME-IMB] body part, or a | ||
588 | [MIME-IMB] header. | ||
589 | |||
590 | 3. State and Flow Diagram | ||
591 | |||
592 | An IMAP4rev1 server is in one of four states. Most commands are | ||
593 | valid in only certain states. It is a protocol error for the client | ||
594 | to attempt a command while the command is in an inappropriate state. | ||
595 | In this case, a server will respond with a BAD or NO (depending upon | ||
596 | server implementation) command completion result. | ||
597 | |||
598 | 3.1. Non-Authenticated State | ||
599 | |||
600 | In non-authenticated state, the client MUST supply authentication | ||
601 | credentials before most commands will be permitted. This state is | ||
602 | entered when a connection starts unless the connection has been pre- | ||
603 | authenticated. | ||
604 | |||
605 | 3.2. Authenticated State | ||
606 | |||
607 | In authenticated state, the client is authenticated and MUST select a | ||
608 | mailbox to access before commands that affect messages will be | ||
609 | permitted. This state is entered when a pre-authenticated connection | ||
610 | starts, when acceptable authentication credentials have been | ||
611 | provided, or after an error in selecting a mailbox. | ||
612 | |||
613 | |||
614 | |||
615 | |||
616 | |||
617 | |||
618 | Crispin Standards Track [Page 11] | ||
619 | |||
620 | RFC 2060 IMAP4rev1 December 1996 | ||
621 | |||
622 | |||
623 | 3.3. Selected State | ||
624 | |||
625 | In selected state, a mailbox has been selected to access. This state | ||
626 | is entered when a mailbox has been successfully selected. | ||
627 | |||
628 | 3.4. Logout State | ||
629 | |||
630 | In logout state, the connection is being terminated, and the server | ||
631 | will close the connection. This state can be entered as a result of | ||
632 | a client request or by unilateral server decision. | ||
633 | |||
634 | +--------------------------------------+ | ||
635 | |initial connection and server greeting| | ||
636 | +--------------------------------------+ | ||
637 | || (1) || (2) || (3) | ||
638 | VV || || | ||
639 | +-----------------+ || || | ||
640 | |non-authenticated| || || | ||
641 | +-----------------+ || || | ||
642 | || (7) || (4) || || | ||
643 | || VV VV || | ||
644 | || +----------------+ || | ||
645 | || | authenticated |<=++ || | ||
646 | || +----------------+ || || | ||
647 | || || (7) || (5) || (6) || | ||
648 | || || VV || || | ||
649 | || || +--------+ || || | ||
650 | || || |selected|==++ || | ||
651 | || || +--------+ || | ||
652 | || || || (7) || | ||
653 | VV VV VV VV | ||
654 | +--------------------------------------+ | ||
655 | | logout and close connection | | ||
656 | +--------------------------------------+ | ||
657 | |||
658 | (1) connection without pre-authentication (OK greeting) | ||
659 | (2) pre-authenticated connection (PREAUTH greeting) | ||
660 | (3) rejected connection (BYE greeting) | ||
661 | (4) successful LOGIN or AUTHENTICATE command | ||
662 | (5) successful SELECT or EXAMINE command | ||
663 | (6) CLOSE command, or failed SELECT or EXAMINE command | ||
664 | (7) LOGOUT command, server shutdown, or connection closed | ||
665 | |||
666 | 4. Data Formats | ||
667 | |||
668 | IMAP4rev1 uses textual commands and responses. Data in IMAP4rev1 can | ||
669 | be in one of several forms: atom, number, string, parenthesized list, | ||
670 | or NIL. | ||
671 | |||
672 | |||
673 | |||
674 | Crispin Standards Track [Page 12] | ||
675 | |||
676 | RFC 2060 IMAP4rev1 December 1996 | ||
677 | |||
678 | |||
679 | 4.1. Atom | ||
680 | |||
681 | An atom consists of one or more non-special characters. | ||
682 | |||
683 | 4.2. Number | ||
684 | |||
685 | A number consists of one or more digit characters, and represents a | ||
686 | numeric value. | ||
687 | |||
688 | 4.3. String | ||
689 | |||
690 | A string is in one of two forms: literal and quoted string. The | ||
691 | literal form is the general form of string. The quoted string form | ||
692 | is an alternative that avoids the overhead of processing a literal at | ||
693 | the cost of limitations of characters that can be used in a quoted | ||
694 | string. | ||
695 | |||
696 | A literal is a sequence of zero or more octets (including CR and LF), | ||
697 | prefix-quoted with an octet count in the form of an open brace ("{"), | ||
698 | the number of octets, close brace ("}"), and CRLF. In the case of | ||
699 | literals transmitted from server to client, the CRLF is immediately | ||
700 | followed by the octet data. In the case of literals transmitted from | ||
701 | client to server, the client MUST wait to receive a command | ||
702 | continuation request (described later in this document) before | ||
703 | sending the octet data (and the remainder of the command). | ||
704 | |||
705 | A quoted string is a sequence of zero or more 7-bit characters, | ||
706 | excluding CR and LF, with double quote (<">) characters at each end. | ||
707 | |||
708 | The empty string is represented as either "" (a quoted string with | ||
709 | zero characters between double quotes) or as {0} followed by CRLF (a | ||
710 | literal with an octet count of 0). | ||
711 | |||
712 | Note: Even if the octet count is 0, a client transmitting a | ||
713 | literal MUST wait to receive a command continuation request. | ||
714 | |||
715 | 4.3.1. 8-bit and Binary Strings | ||
716 | |||
717 | 8-bit textual and binary mail is supported through the use of a | ||
718 | [MIME-IMB] content transfer encoding. IMAP4rev1 implementations MAY | ||
719 | transmit 8-bit or multi-octet characters in literals, but SHOULD do | ||
720 | so only when the [CHARSET] is identified. | ||
721 | |||
722 | |||
723 | |||
724 | |||
725 | |||
726 | |||
727 | |||
728 | |||
729 | |||
730 | Crispin Standards Track [Page 13] | ||
731 | |||
732 | RFC 2060 IMAP4rev1 December 1996 | ||
733 | |||
734 | |||
735 | Although a BINARY body encoding is defined, unencoded binary strings | ||
736 | are not permitted. A "binary string" is any string with NUL | ||
737 | characters. Implementations MUST encode binary data into a textual | ||
738 | form such as BASE64 before transmitting the data. A string with an | ||
739 | excessive amount of CTL characters MAY also be considered to be | ||
740 | binary. | ||
741 | |||
742 | 4.4. Parenthesized List | ||
743 | |||
744 | Data structures are represented as a "parenthesized list"; a sequence | ||
745 | of data items, delimited by space, and bounded at each end by | ||
746 | parentheses. A parenthesized list can contain other parenthesized | ||
747 | lists, using multiple levels of parentheses to indicate nesting. | ||
748 | |||
749 | The empty list is represented as () -- a parenthesized list with no | ||
750 | members. | ||
751 | |||
752 | 4.5. NIL | ||
753 | |||
754 | The special atom "NIL" represents the non-existence of a particular | ||
755 | data item that is represented as a string or parenthesized list, as | ||
756 | distinct from the empty string "" or the empty parenthesized list (). | ||
757 | |||
758 | 5. Operational Considerations | ||
759 | |||
760 | 5.1. Mailbox Naming | ||
761 | |||
762 | The interpretation of mailbox names is implementation-dependent. | ||
763 | However, the case-insensitive mailbox name INBOX is a special name | ||
764 | reserved to mean "the primary mailbox for this user on this server". | ||
765 | |||
766 | 5.1.1. Mailbox Hierarchy Naming | ||
767 | |||
768 | If it is desired to export hierarchical mailbox names, mailbox names | ||
769 | MUST be left-to-right hierarchical using a single character to | ||
770 | separate levels of hierarchy. The same hierarchy separator character | ||
771 | is used for all levels of hierarchy within a single name. | ||
772 | |||
773 | 5.1.2. Mailbox Namespace Naming Convention | ||
774 | |||
775 | By convention, the first hierarchical element of any mailbox name | ||
776 | which begins with "#" identifies the "namespace" of the remainder of | ||
777 | the name. This makes it possible to disambiguate between different | ||
778 | types of mailbox stores, each of which have their own namespaces. | ||
779 | |||
780 | |||
781 | |||
782 | |||
783 | |||
784 | |||
785 | |||
786 | Crispin Standards Track [Page 14] | ||
787 | |||
788 | RFC 2060 IMAP4rev1 December 1996 | ||
789 | |||
790 | |||
791 | For example, implementations which offer access to USENET | ||
792 | newsgroups MAY use the "#news" namespace to partition the USENET | ||
793 | newsgroup namespace from that of other mailboxes. Thus, the | ||
794 | comp.mail.misc newsgroup would have an mailbox name of | ||
795 | "#news.comp.mail.misc", and the name "comp.mail.misc" could refer | ||
796 | to a different object (e.g. a user's private mailbox). | ||
797 | |||
798 | 5.1.3. Mailbox International Naming Convention | ||
799 | |||
800 | By convention, international mailbox names are specified using a | ||
801 | modified version of the UTF-7 encoding described in [UTF-7]. The | ||
802 | purpose of these modifications is to correct the following problems | ||
803 | with UTF-7: | ||
804 | |||
805 | 1) UTF-7 uses the "+" character for shifting; this conflicts with | ||
806 | the common use of "+" in mailbox names, in particular USENET | ||
807 | newsgroup names. | ||
808 | |||
809 | 2) UTF-7's encoding is BASE64 which uses the "/" character; this | ||
810 | conflicts with the use of "/" as a popular hierarchy delimiter. | ||
811 | |||
812 | 3) UTF-7 prohibits the unencoded usage of "\"; this conflicts with | ||
813 | the use of "\" as a popular hierarchy delimiter. | ||
814 | |||
815 | 4) UTF-7 prohibits the unencoded usage of "~"; this conflicts with | ||
816 | the use of "~" in some servers as a home directory indicator. | ||
817 | |||
818 | 5) UTF-7 permits multiple alternate forms to represent the same | ||
819 | string; in particular, printable US-ASCII chararacters can be | ||
820 | represented in encoded form. | ||
821 | |||
822 | In modified UTF-7, printable US-ASCII characters except for "&" | ||
823 | represent themselves; that is, characters with octet values 0x20-0x25 | ||
824 | and 0x27-0x7e. The character "&" (0x26) is represented by the two- | ||
825 | octet sequence "&-". | ||
826 | |||
827 | All other characters (octet values 0x00-0x1f, 0x7f-0xff, and all | ||
828 | Unicode 16-bit octets) are represented in modified BASE64, with a | ||
829 | further modification from [UTF-7] that "," is used instead of "/". | ||
830 | Modified BASE64 MUST NOT be used to represent any printing US-ASCII | ||
831 | character which can represent itself. | ||
832 | |||
833 | "&" is used to shift to modified BASE64 and "-" to shift back to US- | ||
834 | ASCII. All names start in US-ASCII, and MUST end in US-ASCII (that | ||
835 | is, a name that ends with a Unicode 16-bit octet MUST end with a "- | ||
836 | "). | ||
837 | |||
838 | |||
839 | |||
840 | |||
841 | |||
842 | Crispin Standards Track [Page 15] | ||
843 | |||
844 | RFC 2060 IMAP4rev1 December 1996 | ||
845 | |||
846 | |||
847 | For example, here is a mailbox name which mixes English, Japanese, | ||
848 | and Chinese text: ~peter/mail/&ZeVnLIqe-/&U,BTFw- | ||
849 | |||
850 | 5.2. Mailbox Size and Message Status Updates | ||
851 | |||
852 | At any time, a server can send data that the client did not request. | ||
853 | Sometimes, such behavior is REQUIRED. For example, agents other than | ||
854 | the server MAY add messages to the mailbox (e.g. new mail delivery), | ||
855 | change the flags of message in the mailbox (e.g. simultaneous access | ||
856 | to the same mailbox by multiple agents), or even remove messages from | ||
857 | the mailbox. A server MUST send mailbox size updates automatically | ||
858 | if a mailbox size change is observed during the processing of a | ||
859 | command. A server SHOULD send message flag updates automatically, | ||
860 | without requiring the client to request such updates explicitly. | ||
861 | Special rules exist for server notification of a client about the | ||
862 | removal of messages to prevent synchronization errors; see the | ||
863 | description of the EXPUNGE response for more detail. | ||
864 | |||
865 | Regardless of what implementation decisions a client makes on | ||
866 | remembering data from the server, a client implementation MUST record | ||
867 | mailbox size updates. It MUST NOT assume that any command after | ||
868 | initial mailbox selection will return the size of the mailbox. | ||
869 | |||
870 | 5.3. Response when no Command in Progress | ||
871 | |||
872 | Server implementations are permitted to send an untagged response | ||
873 | (except for EXPUNGE) while there is no command in progress. Server | ||
874 | implementations that send such responses MUST deal with flow control | ||
875 | considerations. Specifically, they MUST either (1) verify that the | ||
876 | size of the data does not exceed the underlying transport's available | ||
877 | window size, or (2) use non-blocking writes. | ||
878 | |||
879 | 5.4. Autologout Timer | ||
880 | |||
881 | If a server has an inactivity autologout timer, that timer MUST be of | ||
882 | at least 30 minutes' duration. The receipt of ANY command from the | ||
883 | client during that interval SHOULD suffice to reset the autologout | ||
884 | timer. | ||
885 | |||
886 | |||
887 | |||
888 | |||
889 | |||
890 | |||
891 | |||
892 | |||
893 | |||
894 | |||
895 | |||
896 | |||
897 | |||
898 | Crispin Standards Track [Page 16] | ||
899 | |||
900 | RFC 2060 IMAP4rev1 December 1996 | ||
901 | |||
902 | |||
903 | 5.5. Multiple Commands in Progress | ||
904 | |||
905 | The client MAY send another command without waiting for the | ||
906 | completion result response of a command, subject to ambiguity rules | ||
907 | (see below) and flow control constraints on the underlying data | ||
908 | stream. Similarly, a server MAY begin processing another command | ||
909 | before processing the current command to completion, subject to | ||
910 | ambiguity rules. However, any command continuation request responses | ||
911 | and command continuations MUST be negotiated before any subsequent | ||
912 | command is initiated. | ||
913 | |||
914 | The exception is if an ambiguity would result because of a command | ||
915 | that would affect the results of other commands. Clients MUST NOT | ||
916 | send multiple commands without waiting if an ambiguity would result. | ||
917 | If the server detects a possible ambiguity, it MUST execute commands | ||
918 | to completion in the order given by the client. | ||
919 | |||
920 | The most obvious example of ambiguity is when a command would affect | ||
921 | the results of another command; for example, a FETCH of a message's | ||
922 | flags and a STORE of that same message's flags. | ||
923 | |||
924 | A non-obvious ambiguity occurs with commands that permit an untagged | ||
925 | EXPUNGE response (commands other than FETCH, STORE, and SEARCH), | ||
926 | since an untagged EXPUNGE response can invalidate sequence numbers in | ||
927 | a subsequent command. This is not a problem for FETCH, STORE, or | ||
928 | SEARCH commands because servers are prohibited from sending EXPUNGE | ||
929 | responses while any of those commands are in progress. Therefore, if | ||
930 | the client sends any command other than FETCH, STORE, or SEARCH, it | ||
931 | MUST wait for a response before sending a command with message | ||
932 | sequence numbers. | ||
933 | |||
934 | For example, the following non-waiting command sequences are invalid: | ||
935 | |||
936 | FETCH + NOOP + STORE | ||
937 | STORE + COPY + FETCH | ||
938 | COPY + COPY | ||
939 | CHECK + FETCH | ||
940 | |||
941 | The following are examples of valid non-waiting command sequences: | ||
942 | |||
943 | FETCH + STORE + SEARCH + CHECK | ||
944 | STORE + COPY + EXPUNGE | ||
945 | |||
946 | 6. Client Commands | ||
947 | |||
948 | IMAP4rev1 commands are described in this section. Commands are | ||
949 | organized by the state in which the command is permitted. Commands | ||
950 | which are permitted in multiple states are listed in the minimum | ||
951 | |||
952 | |||
953 | |||
954 | Crispin Standards Track [Page 17] | ||
955 | |||
956 | RFC 2060 IMAP4rev1 December 1996 | ||
957 | |||
958 | |||
959 | permitted state (for example, commands valid in authenticated and | ||
960 | selected state are listed in the authenticated state commands). | ||
961 | |||
962 | Command arguments, identified by "Arguments:" in the command | ||
963 | descriptions below, are described by function, not by syntax. The | ||
964 | precise syntax of command arguments is described in the Formal Syntax | ||
965 | section. | ||
966 | |||
967 | Some commands cause specific server responses to be returned; these | ||
968 | are identified by "Responses:" in the command descriptions below. | ||
969 | See the response descriptions in the Responses section for | ||
970 | information on these responses, and the Formal Syntax section for the | ||
971 | precise syntax of these responses. It is possible for server data to | ||
972 | be transmitted as a result of any command; thus, commands that do not | ||
973 | specifically require server data specify "no specific responses for | ||
974 | this command" instead of "none". | ||
975 | |||
976 | The "Result:" in the command description refers to the possible | ||
977 | tagged status responses to a command, and any special interpretation | ||
978 | of these status responses. | ||
979 | |||
980 | 6.1. Client Commands - Any State | ||
981 | |||
982 | The following commands are valid in any state: CAPABILITY, NOOP, and | ||
983 | LOGOUT. | ||
984 | |||
985 | 6.1.1. CAPABILITY Command | ||
986 | |||
987 | Arguments: none | ||
988 | |||
989 | Responses: REQUIRED untagged response: CAPABILITY | ||
990 | |||
991 | Result: OK - capability completed | ||
992 | BAD - command unknown or arguments invalid | ||
993 | |||
994 | The CAPABILITY command requests a listing of capabilities that the | ||
995 | server supports. The server MUST send a single untagged | ||
996 | CAPABILITY response with "IMAP4rev1" as one of the listed | ||
997 | capabilities before the (tagged) OK response. This listing of | ||
998 | capabilities is not dependent upon connection state or user. It | ||
999 | is therefore not necessary to issue a CAPABILITY command more than | ||
1000 | once in a connection. | ||
1001 | |||
1002 | |||
1003 | |||
1004 | |||
1005 | |||
1006 | |||
1007 | |||
1008 | |||
1009 | |||
1010 | Crispin Standards Track [Page 18] | ||
1011 | |||
1012 | RFC 2060 IMAP4rev1 December 1996 | ||
1013 | |||
1014 | |||
1015 | A capability name which begins with "AUTH=" indicates that the | ||
1016 | server supports that particular authentication mechanism. All | ||
1017 | such names are, by definition, part of this specification. For | ||
1018 | example, the authorization capability for an experimental | ||
1019 | "blurdybloop" authenticator would be "AUTH=XBLURDYBLOOP" and not | ||
1020 | "XAUTH=BLURDYBLOOP" or "XAUTH=XBLURDYBLOOP". | ||
1021 | |||
1022 | Other capability names refer to extensions, revisions, or | ||
1023 | amendments to this specification. See the documentation of the | ||
1024 | CAPABILITY response for additional information. No capabilities, | ||
1025 | beyond the base IMAP4rev1 set defined in this specification, are | ||
1026 | enabled without explicit client action to invoke the capability. | ||
1027 | |||
1028 | See the section entitled "Client Commands - | ||
1029 | Experimental/Expansion" for information about the form of site or | ||
1030 | implementation-specific capabilities. | ||
1031 | |||
1032 | Example: C: abcd CAPABILITY | ||
1033 | S: * CAPABILITY IMAP4rev1 AUTH=KERBEROS_V4 | ||
1034 | S: abcd OK CAPABILITY completed | ||
1035 | |||
1036 | 6.1.2. NOOP Command | ||
1037 | |||
1038 | Arguments: none | ||
1039 | |||
1040 | Responses: no specific responses for this command (but see below) | ||
1041 | |||
1042 | Result: OK - noop completed | ||
1043 | BAD - command unknown or arguments invalid | ||
1044 | |||
1045 | The NOOP command always succeeds. It does nothing. | ||
1046 | |||
1047 | Since any command can return a status update as untagged data, the | ||
1048 | NOOP command can be used as a periodic poll for new messages or | ||
1049 | message status updates during a period of inactivity. The NOOP | ||
1050 | command can also be used to reset any inactivity autologout timer | ||
1051 | on the server. | ||
1052 | |||
1053 | Example: C: a002 NOOP | ||
1054 | S: a002 OK NOOP completed | ||
1055 | . . . | ||
1056 | C: a047 NOOP | ||
1057 | S: * 22 EXPUNGE | ||
1058 | S: * 23 EXISTS | ||
1059 | S: * 3 RECENT | ||
1060 | S: * 14 FETCH (FLAGS (\Seen \Deleted)) | ||
1061 | S: a047 OK NOOP completed | ||
1062 | |||
1063 | |||
1064 | |||
1065 | |||
1066 | Crispin Standards Track [Page 19] | ||
1067 | |||
1068 | RFC 2060 IMAP4rev1 December 1996 | ||
1069 | |||
1070 | |||
1071 | 6.1.3. LOGOUT Command | ||
1072 | |||
1073 | Arguments: none | ||
1074 | |||
1075 | Responses: REQUIRED untagged response: BYE | ||
1076 | |||
1077 | Result: OK - logout completed | ||
1078 | BAD - command unknown or arguments invalid | ||
1079 | |||
1080 | The LOGOUT command informs the server that the client is done with | ||
1081 | the connection. The server MUST send a BYE untagged response | ||
1082 | before the (tagged) OK response, and then close the network | ||
1083 | connection. | ||
1084 | |||
1085 | Example: C: A023 LOGOUT | ||
1086 | S: * BYE IMAP4rev1 Server logging out | ||
1087 | S: A023 OK LOGOUT completed | ||
1088 | (Server and client then close the connection) | ||
1089 | |||
1090 | 6.2. Client Commands - Non-Authenticated State | ||
1091 | |||
1092 | In non-authenticated state, the AUTHENTICATE or LOGIN command | ||
1093 | establishes authentication and enter authenticated state. The | ||
1094 | AUTHENTICATE command provides a general mechanism for a variety of | ||
1095 | authentication techniques, whereas the LOGIN command uses the | ||
1096 | traditional user name and plaintext password pair. | ||
1097 | |||
1098 | Server implementations MAY allow non-authenticated access to certain | ||
1099 | mailboxes. The convention is to use a LOGIN command with the userid | ||
1100 | "anonymous". A password is REQUIRED. It is implementation-dependent | ||
1101 | what requirements, if any, are placed on the password and what access | ||
1102 | restrictions are placed on anonymous users. | ||
1103 | |||
1104 | Once authenticated (including as anonymous), it is not possible to | ||
1105 | re-enter non-authenticated state. | ||
1106 | |||
1107 | In addition to the universal commands (CAPABILITY, NOOP, and LOGOUT), | ||
1108 | the following commands are valid in non-authenticated state: | ||
1109 | AUTHENTICATE and LOGIN. | ||
1110 | |||
1111 | |||
1112 | |||
1113 | |||
1114 | |||
1115 | |||
1116 | |||
1117 | |||
1118 | |||
1119 | |||
1120 | |||
1121 | |||
1122 | Crispin Standards Track [Page 20] | ||
1123 | |||
1124 | RFC 2060 IMAP4rev1 December 1996 | ||
1125 | |||
1126 | |||
1127 | 6.2.1. AUTHENTICATE Command | ||
1128 | |||
1129 | Arguments: authentication mechanism name | ||
1130 | |||
1131 | Responses: continuation data can be requested | ||
1132 | |||
1133 | Result: OK - authenticate completed, now in authenticated state | ||
1134 | NO - authenticate failure: unsupported authentication | ||
1135 | mechanism, credentials rejected | ||
1136 | BAD - command unknown or arguments invalid, | ||
1137 | authentication exchange cancelled | ||
1138 | |||
1139 | The AUTHENTICATE command indicates an authentication mechanism, | ||
1140 | such as described in [IMAP-AUTH], to the server. If the server | ||
1141 | supports the requested authentication mechanism, it performs an | ||
1142 | authentication protocol exchange to authenticate and identify the | ||
1143 | client. It MAY also negotiate an OPTIONAL protection mechanism | ||
1144 | for subsequent protocol interactions. If the requested | ||
1145 | authentication mechanism is not supported, the server SHOULD | ||
1146 | reject the AUTHENTICATE command by sending a tagged NO response. | ||
1147 | |||
1148 | The authentication protocol exchange consists of a series of | ||
1149 | server challenges and client answers that are specific to the | ||
1150 | authentication mechanism. A server challenge consists of a | ||
1151 | command continuation request response with the "+" token followed | ||
1152 | by a BASE64 encoded string. The client answer consists of a line | ||
1153 | consisting of a BASE64 encoded string. If the client wishes to | ||
1154 | cancel an authentication exchange, it issues a line with a single | ||
1155 | "*". If the server receives such an answer, it MUST reject the | ||
1156 | AUTHENTICATE command by sending a tagged BAD response. | ||
1157 | |||
1158 | A protection mechanism provides integrity and privacy protection | ||
1159 | to the connection. If a protection mechanism is negotiated, it is | ||
1160 | applied to all subsequent data sent over the connection. The | ||
1161 | protection mechanism takes effect immediately following the CRLF | ||
1162 | that concludes the authentication exchange for the client, and the | ||
1163 | CRLF of the tagged OK response for the server. Once the | ||
1164 | protection mechanism is in effect, the stream of command and | ||
1165 | response octets is processed into buffers of ciphertext. Each | ||
1166 | buffer is transferred over the connection as a stream of octets | ||
1167 | prepended with a four octet field in network byte order that | ||
1168 | represents the length of the following data. The maximum | ||
1169 | ciphertext buffer length is defined by the protection mechanism. | ||
1170 | |||
1171 | Authentication mechanisms are OPTIONAL. Protection mechanisms are | ||
1172 | also OPTIONAL; an authentication mechanism MAY be implemented | ||
1173 | without any protection mechanism. If an AUTHENTICATE command | ||
1174 | fails with a NO response, the client MAY try another | ||
1175 | |||
1176 | |||
1177 | |||
1178 | Crispin Standards Track [Page 21] | ||
1179 | |||
1180 | RFC 2060 IMAP4rev1 December 1996 | ||
1181 | |||
1182 | |||
1183 | authentication mechanism by issuing another AUTHENTICATE command, | ||
1184 | or MAY attempt to authenticate by using the LOGIN command. In | ||
1185 | other words, the client MAY request authentication types in | ||
1186 | decreasing order of preference, with the LOGIN command as a last | ||
1187 | resort. | ||
1188 | |||
1189 | Example: S: * OK KerberosV4 IMAP4rev1 Server | ||
1190 | C: A001 AUTHENTICATE KERBEROS_V4 | ||
1191 | S: + AmFYig== | ||
1192 | C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT | ||
1193 | +nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd | ||
1194 | WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh | ||
1195 | S: + or//EoAADZI= | ||
1196 | C: DiAF5A4gA+oOIALuBkAAmw== | ||
1197 | S: A001 OK Kerberos V4 authentication successful | ||
1198 | |||
1199 | Note: the line breaks in the first client answer are for editorial | ||
1200 | clarity and are not in real authenticators. | ||
1201 | |||
1202 | 6.2.2. LOGIN Command | ||
1203 | |||
1204 | Arguments: user name | ||
1205 | password | ||
1206 | |||
1207 | Responses: no specific responses for this command | ||
1208 | |||
1209 | Result: OK - login completed, now in authenticated state | ||
1210 | NO - login failure: user name or password rejected | ||
1211 | BAD - command unknown or arguments invalid | ||
1212 | |||
1213 | The LOGIN command identifies the client to the server and carries | ||
1214 | the plaintext password authenticating this user. | ||
1215 | |||
1216 | Example: C: a001 LOGIN SMITH SESAME | ||
1217 | S: a001 OK LOGIN completed | ||
1218 | |||
1219 | 6.3. Client Commands - Authenticated State | ||
1220 | |||
1221 | In authenticated state, commands that manipulate mailboxes as atomic | ||
1222 | entities are permitted. Of these commands, the SELECT and EXAMINE | ||
1223 | commands will select a mailbox for access and enter selected state. | ||
1224 | |||
1225 | In addition to the universal commands (CAPABILITY, NOOP, and LOGOUT), | ||
1226 | the following commands are valid in authenticated state: SELECT, | ||
1227 | EXAMINE, CREATE, DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE, LIST, LSUB, | ||
1228 | STATUS, and APPEND. | ||
1229 | |||
1230 | |||
1231 | |||
1232 | |||
1233 | |||
1234 | Crispin Standards Track [Page 22] | ||
1235 | |||
1236 | RFC 2060 IMAP4rev1 December 1996 | ||
1237 | |||
1238 | |||
1239 | 6.3.1. SELECT Command | ||
1240 | |||
1241 | Arguments: mailbox name | ||
1242 | |||
1243 | Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT | ||
1244 | OPTIONAL OK untagged responses: UNSEEN, PERMANENTFLAGS | ||
1245 | |||
1246 | Result: OK - select completed, now in selected state | ||
1247 | NO - select failure, now in authenticated state: no | ||
1248 | such mailbox, can't access mailbox | ||
1249 | BAD - command unknown or arguments invalid | ||
1250 | |||
1251 | The SELECT command selects a mailbox so that messages in the | ||
1252 | mailbox can be accessed. Before returning an OK to the client, | ||
1253 | the server MUST send the following untagged data to the client: | ||
1254 | |||
1255 | FLAGS Defined flags in the mailbox. See the description | ||
1256 | of the FLAGS response for more detail. | ||
1257 | |||
1258 | <n> EXISTS The number of messages in the mailbox. See the | ||
1259 | description of the EXISTS response for more detail. | ||
1260 | |||
1261 | <n> RECENT The number of messages with the \Recent flag set. | ||
1262 | See the description of the RECENT response for more | ||
1263 | detail. | ||
1264 | |||
1265 | OK [UIDVALIDITY <n>] | ||
1266 | The unique identifier validity value. See the | ||
1267 | description of the UID command for more detail. | ||
1268 | |||
1269 | to define the initial state of the mailbox at the client. | ||
1270 | |||
1271 | The server SHOULD also send an UNSEEN response code in an OK | ||
1272 | untagged response, indicating the message sequence number of the | ||
1273 | first unseen message in the mailbox. | ||
1274 | |||
1275 | If the client can not change the permanent state of one or more of | ||
1276 | the flags listed in the FLAGS untagged response, the server SHOULD | ||
1277 | send a PERMANENTFLAGS response code in an OK untagged response, | ||
1278 | listing the flags that the client can change permanently. | ||
1279 | |||
1280 | Only one mailbox can be selected at a time in a connection; | ||
1281 | simultaneous access to multiple mailboxes requires multiple | ||
1282 | connections. The SELECT command automatically deselects any | ||
1283 | currently selected mailbox before attempting the new selection. | ||
1284 | Consequently, if a mailbox is selected and a SELECT command that | ||
1285 | fails is attempted, no mailbox is selected. | ||
1286 | |||
1287 | |||
1288 | |||
1289 | |||
1290 | Crispin Standards Track [Page 23] | ||
1291 | |||
1292 | RFC 2060 IMAP4rev1 December 1996 | ||
1293 | |||
1294 | |||
1295 | If the client is permitted to modify the mailbox, the server | ||
1296 | SHOULD prefix the text of the tagged OK response with the | ||
1297 | "[READ-WRITE]" response code. | ||
1298 | |||
1299 | If the client is not permitted to modify the mailbox but is | ||
1300 | permitted read access, the mailbox is selected as read-only, and | ||
1301 | the server MUST prefix the text of the tagged OK response to | ||
1302 | SELECT with the "[READ-ONLY]" response code. Read-only access | ||
1303 | through SELECT differs from the EXAMINE command in that certain | ||
1304 | read-only mailboxes MAY permit the change of permanent state on a | ||
1305 | per-user (as opposed to global) basis. Netnews messages marked in | ||
1306 | a server-based .newsrc file are an example of such per-user | ||
1307 | permanent state that can be modified with read-only mailboxes. | ||
1308 | |||
1309 | Example: C: A142 SELECT INBOX | ||
1310 | S: * 172 EXISTS | ||
1311 | S: * 1 RECENT | ||
1312 | S: * OK [UNSEEN 12] Message 12 is first unseen | ||
1313 | S: * OK [UIDVALIDITY 3857529045] UIDs valid | ||
1314 | S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) | ||
1315 | S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited | ||
1316 | S: A142 OK [READ-WRITE] SELECT completed | ||
1317 | |||
1318 | 6.3.2. EXAMINE Command | ||
1319 | |||
1320 | Arguments: mailbox name | ||
1321 | |||
1322 | Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT | ||
1323 | OPTIONAL OK untagged responses: UNSEEN, PERMANENTFLAGS | ||
1324 | |||
1325 | Result: OK - examine completed, now in selected state | ||
1326 | NO - examine failure, now in authenticated state: no | ||
1327 | such mailbox, can't access mailbox | ||
1328 | BAD - command unknown or arguments invalid | ||
1329 | |||
1330 | The EXAMINE command is identical to SELECT and returns the same | ||
1331 | output; however, the selected mailbox is identified as read-only. | ||
1332 | No changes to the permanent state of the mailbox, including | ||
1333 | per-user state, are permitted. | ||
1334 | |||
1335 | |||
1336 | |||
1337 | |||
1338 | |||
1339 | |||
1340 | |||
1341 | |||
1342 | |||
1343 | |||
1344 | |||
1345 | |||
1346 | Crispin Standards Track [Page 24] | ||
1347 | |||
1348 | RFC 2060 IMAP4rev1 December 1996 | ||
1349 | |||
1350 | |||
1351 | The text of the tagged OK response to the EXAMINE command MUST | ||
1352 | begin with the "[READ-ONLY]" response code. | ||
1353 | |||
1354 | Example: C: A932 EXAMINE blurdybloop | ||
1355 | S: * 17 EXISTS | ||
1356 | S: * 2 RECENT | ||
1357 | S: * OK [UNSEEN 8] Message 8 is first unseen | ||
1358 | S: * OK [UIDVALIDITY 3857529045] UIDs valid | ||
1359 | S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) | ||
1360 | S: * OK [PERMANENTFLAGS ()] No permanent flags permitted | ||
1361 | S: A932 OK [READ-ONLY] EXAMINE completed | ||
1362 | |||
1363 | 6.3.3. CREATE Command | ||
1364 | |||
1365 | Arguments: mailbox name | ||
1366 | |||
1367 | Responses: no specific responses for this command | ||
1368 | |||
1369 | Result: OK - create completed | ||
1370 | NO - create failure: can't create mailbox with that name | ||
1371 | BAD - command unknown or arguments invalid | ||
1372 | |||
1373 | The CREATE command creates a mailbox with the given name. An OK | ||
1374 | response is returned only if a new mailbox with that name has been | ||
1375 | created. It is an error to attempt to create INBOX or a mailbox | ||
1376 | with a name that refers to an extant mailbox. Any error in | ||
1377 | creation will return a tagged NO response. | ||
1378 | |||
1379 | If the mailbox name is suffixed with the server's hierarchy | ||
1380 | separator character (as returned from the server by a LIST | ||
1381 | command), this is a declaration that the client intends to create | ||
1382 | mailbox names under this name in the hierarchy. Server | ||
1383 | implementations that do not require this declaration MUST ignore | ||
1384 | it. | ||
1385 | |||
1386 | If the server's hierarchy separator character appears elsewhere in | ||
1387 | the name, the server SHOULD create any superior hierarchical names | ||
1388 | that are needed for the CREATE command to complete successfully. | ||
1389 | In other words, an attempt to create "foo/bar/zap" on a server in | ||
1390 | which "/" is the hierarchy separator character SHOULD create foo/ | ||
1391 | and foo/bar/ if they do not already exist. | ||
1392 | |||
1393 | If a new mailbox is created with the same name as a mailbox which | ||
1394 | was deleted, its unique identifiers MUST be greater than any | ||
1395 | unique identifiers used in the previous incarnation of the mailbox | ||
1396 | UNLESS the new incarnation has a different unique identifier | ||
1397 | validity value. See the description of the UID command for more | ||
1398 | detail. | ||
1399 | |||
1400 | |||
1401 | |||
1402 | Crispin Standards Track [Page 25] | ||
1403 | |||
1404 | RFC 2060 IMAP4rev1 December 1996 | ||
1405 | |||
1406 | |||
1407 | Example: C: A003 CREATE owatagusiam/ | ||
1408 | S: A003 OK CREATE completed | ||
1409 | C: A004 CREATE owatagusiam/blurdybloop | ||
1410 | S: A004 OK CREATE completed | ||
1411 | |||
1412 | Note: the interpretation of this example depends on whether "/" | ||
1413 | was returned as the hierarchy separator from LIST. If "/" is the | ||
1414 | hierarchy separator, a new level of hierarchy named "owatagusiam" | ||
1415 | with a member called "blurdybloop" is created. Otherwise, two | ||
1416 | mailboxes at the same hierarchy level are created. | ||
1417 | |||
1418 | 6.3.4. DELETE Command | ||
1419 | |||
1420 | Arguments: mailbox name | ||
1421 | |||
1422 | Responses: no specific responses for this command | ||
1423 | |||
1424 | Result: OK - delete completed | ||
1425 | NO - delete failure: can't delete mailbox with that name | ||
1426 | BAD - command unknown or arguments invalid | ||
1427 | |||
1428 | The DELETE command permanently removes the mailbox with the given | ||
1429 | name. A tagged OK response is returned only if the mailbox has | ||
1430 | been deleted. It is an error to attempt to delete INBOX or a | ||
1431 | mailbox name that does not exist. | ||
1432 | |||
1433 | The DELETE command MUST NOT remove inferior hierarchical names. | ||
1434 | For example, if a mailbox "foo" has an inferior "foo.bar" | ||
1435 | (assuming "." is the hierarchy delimiter character), removing | ||
1436 | "foo" MUST NOT remove "foo.bar". It is an error to attempt to | ||
1437 | delete a name that has inferior hierarchical names and also has | ||
1438 | the \Noselect mailbox name attribute (see the description of the | ||
1439 | LIST response for more details). | ||
1440 | |||
1441 | It is permitted to delete a name that has inferior hierarchical | ||
1442 | names and does not have the \Noselect mailbox name attribute. In | ||
1443 | this case, all messages in that mailbox are removed, and the name | ||
1444 | will acquire the \Noselect mailbox name attribute. | ||
1445 | |||
1446 | The value of the highest-used unique identifier of the deleted | ||
1447 | mailbox MUST be preserved so that a new mailbox created with the | ||
1448 | same name will not reuse the identifiers of the former | ||
1449 | incarnation, UNLESS the new incarnation has a different unique | ||
1450 | identifier validity value. See the description of the UID command | ||
1451 | for more detail. | ||
1452 | |||
1453 | |||
1454 | |||
1455 | |||
1456 | |||
1457 | |||
1458 | Crispin Standards Track [Page 26] | ||
1459 | |||
1460 | RFC 2060 IMAP4rev1 December 1996 | ||
1461 | |||
1462 | |||
1463 | Examples: C: A682 LIST "" * | ||
1464 | S: * LIST () "/" blurdybloop | ||
1465 | S: * LIST (\Noselect) "/" foo | ||
1466 | S: * LIST () "/" foo/bar | ||
1467 | S: A682 OK LIST completed | ||
1468 | C: A683 DELETE blurdybloop | ||
1469 | S: A683 OK DELETE completed | ||
1470 | C: A684 DELETE foo | ||
1471 | S: A684 NO Name "foo" has inferior hierarchical names | ||
1472 | C: A685 DELETE foo/bar | ||
1473 | S: A685 OK DELETE Completed | ||
1474 | C: A686 LIST "" * | ||
1475 | S: * LIST (\Noselect) "/" foo | ||
1476 | S: A686 OK LIST completed | ||
1477 | C: A687 DELETE foo | ||
1478 | S: A687 OK DELETE Completed | ||
1479 | |||
1480 | |||
1481 | C: A82 LIST "" * | ||
1482 | S: * LIST () "." blurdybloop | ||
1483 | S: * LIST () "." foo | ||
1484 | S: * LIST () "." foo.bar | ||
1485 | S: A82 OK LIST completed | ||
1486 | C: A83 DELETE blurdybloop | ||
1487 | S: A83 OK DELETE completed | ||
1488 | C: A84 DELETE foo | ||
1489 | S: A84 OK DELETE Completed | ||
1490 | C: A85 LIST "" * | ||
1491 | S: * LIST () "." foo.bar | ||
1492 | S: A85 OK LIST completed | ||
1493 | C: A86 LIST "" % | ||
1494 | S: * LIST (\Noselect) "." foo | ||
1495 | S: A86 OK LIST completed | ||
1496 | |||
1497 | 6.3.5. RENAME Command | ||
1498 | |||
1499 | Arguments: existing mailbox name | ||
1500 | new mailbox name | ||
1501 | |||
1502 | Responses: no specific responses for this command | ||
1503 | |||
1504 | Result: OK - rename completed | ||
1505 | NO - rename failure: can't rename mailbox with that name, | ||
1506 | can't rename to mailbox with that name | ||
1507 | BAD - command unknown or arguments invalid | ||
1508 | |||
1509 | The RENAME command changes the name of a mailbox. A tagged OK | ||
1510 | response is returned only if the mailbox has been renamed. It is | ||
1511 | |||
1512 | |||
1513 | |||
1514 | Crispin Standards Track [Page 27] | ||
1515 | |||
1516 | RFC 2060 IMAP4rev1 December 1996 | ||
1517 | |||
1518 | |||
1519 | an error to attempt to rename from a mailbox name that does not | ||
1520 | exist or to a mailbox name that already exists. Any error in | ||
1521 | renaming will return a tagged NO response. | ||
1522 | |||
1523 | If the name has inferior hierarchical names, then the inferior | ||
1524 | hierarchical names MUST also be renamed. For example, a rename of | ||
1525 | "foo" to "zap" will rename "foo/bar" (assuming "/" is the | ||
1526 | hierarchy delimiter character) to "zap/bar". | ||
1527 | |||
1528 | The value of the highest-used unique identifier of the old mailbox | ||
1529 | name MUST be preserved so that a new mailbox created with the same | ||
1530 | name will not reuse the identifiers of the former incarnation, | ||
1531 | UNLESS the new incarnation has a different unique identifier | ||
1532 | validity value. See the description of the UID command for more | ||
1533 | detail. | ||
1534 | |||
1535 | Renaming INBOX is permitted, and has special behavior. It moves | ||
1536 | all messages in INBOX to a new mailbox with the given name, | ||
1537 | leaving INBOX empty. If the server implementation supports | ||
1538 | inferior hierarchical names of INBOX, these are unaffected by a | ||
1539 | rename of INBOX. | ||
1540 | |||
1541 | Examples: C: A682 LIST "" * | ||
1542 | S: * LIST () "/" blurdybloop | ||
1543 | S: * LIST (\Noselect) "/" foo | ||
1544 | S: * LIST () "/" foo/bar | ||
1545 | S: A682 OK LIST completed | ||
1546 | C: A683 RENAME blurdybloop sarasoop | ||
1547 | S: A683 OK RENAME completed | ||
1548 | C: A684 RENAME foo zowie | ||
1549 | S: A684 OK RENAME Completed | ||
1550 | C: A685 LIST "" * | ||
1551 | S: * LIST () "/" sarasoop | ||
1552 | S: * LIST (\Noselect) "/" zowie | ||
1553 | S: * LIST () "/" zowie/bar | ||
1554 | S: A685 OK LIST completed | ||
1555 | |||
1556 | |||
1557 | |||
1558 | |||
1559 | |||
1560 | |||
1561 | |||
1562 | |||
1563 | |||
1564 | |||
1565 | |||
1566 | |||
1567 | |||
1568 | |||
1569 | |||
1570 | Crispin Standards Track [Page 28] | ||
1571 | |||
1572 | RFC 2060 IMAP4rev1 December 1996 | ||
1573 | |||
1574 | |||
1575 | C: Z432 LIST "" * | ||
1576 | S: * LIST () "." INBOX | ||
1577 | S: * LIST () "." INBOX.bar | ||
1578 | S: Z432 OK LIST completed | ||
1579 | C: Z433 RENAME INBOX old-mail | ||
1580 | S: Z433 OK RENAME completed | ||
1581 | C: Z434 LIST "" * | ||
1582 | S: * LIST () "." INBOX | ||
1583 | S: * LIST () "." INBOX.bar | ||
1584 | S: * LIST () "." old-mail | ||
1585 | S: Z434 OK LIST completed | ||
1586 | |||
1587 | 6.3.6. SUBSCRIBE Command | ||
1588 | |||
1589 | Arguments: mailbox | ||
1590 | |||
1591 | Responses: no specific responses for this command | ||
1592 | |||
1593 | Result: OK - subscribe completed | ||
1594 | NO - subscribe failure: can't subscribe to that name | ||
1595 | BAD - command unknown or arguments invalid | ||
1596 | |||
1597 | The SUBSCRIBE command adds the specified mailbox name to the | ||
1598 | server's set of "active" or "subscribed" mailboxes as returned by | ||
1599 | the LSUB command. This command returns a tagged OK response only | ||
1600 | if the subscription is successful. | ||
1601 | |||
1602 | A server MAY validate the mailbox argument to SUBSCRIBE to verify | ||
1603 | that it exists. However, it MUST NOT unilaterally remove an | ||
1604 | existing mailbox name from the subscription list even if a mailbox | ||
1605 | by that name no longer exists. | ||
1606 | |||
1607 | Note: this requirement is because some server sites may routinely | ||
1608 | remove a mailbox with a well-known name (e.g. "system-alerts") | ||
1609 | after its contents expire, with the intention of recreating it | ||
1610 | when new contents are appropriate. | ||
1611 | |||
1612 | Example: C: A002 SUBSCRIBE #news.comp.mail.mime | ||
1613 | S: A002 OK SUBSCRIBE completed | ||
1614 | |||
1615 | |||
1616 | |||
1617 | |||
1618 | |||
1619 | |||
1620 | |||
1621 | |||
1622 | |||
1623 | |||
1624 | |||
1625 | |||
1626 | Crispin Standards Track [Page 29] | ||
1627 | |||
1628 | RFC 2060 IMAP4rev1 December 1996 | ||
1629 | |||
1630 | |||
1631 | 6.3.7. UNSUBSCRIBE Command | ||
1632 | |||
1633 | Arguments: mailbox name | ||
1634 | |||
1635 | Responses: no specific responses for this command | ||
1636 | |||
1637 | Result: OK - unsubscribe completed | ||
1638 | NO - unsubscribe failure: can't unsubscribe that name | ||
1639 | BAD - command unknown or arguments invalid | ||
1640 | |||
1641 | The UNSUBSCRIBE command removes the specified mailbox name from | ||
1642 | the server's set of "active" or "subscribed" mailboxes as returned | ||
1643 | by the LSUB command. This command returns a tagged OK response | ||
1644 | only if the unsubscription is successful. | ||
1645 | |||
1646 | Example: C: A002 UNSUBSCRIBE #news.comp.mail.mime | ||
1647 | S: A002 OK UNSUBSCRIBE completed | ||
1648 | |||
1649 | 6.3..8. LIST Command | ||
1650 | |||
1651 | Arguments: reference name | ||
1652 | mailbox name with possible wildcards | ||
1653 | |||
1654 | Responses: untagged responses: LIST | ||
1655 | |||
1656 | Result: OK - list completed | ||
1657 | NO - list failure: can't list that reference or name | ||
1658 | BAD - command unknown or arguments invalid | ||
1659 | |||
1660 | The LIST command returns a subset of names from the complete set | ||
1661 | of all names available to the client. Zero or more untagged LIST | ||
1662 | replies are returned, containing the name attributes, hierarchy | ||
1663 | delimiter, and name; see the description of the LIST reply for | ||
1664 | more detail. | ||
1665 | |||
1666 | The LIST command SHOULD return its data quickly, without undue | ||
1667 | delay. For example, it SHOULD NOT go to excess trouble to | ||
1668 | calculate \Marked or \Unmarked status or perform other processing; | ||
1669 | if each name requires 1 second of processing, then a list of 1200 | ||
1670 | names would take 20 minutes! | ||
1671 | |||
1672 | An empty ("" string) reference name argument indicates that the | ||
1673 | mailbox name is interpreted as by SELECT. The returned mailbox | ||
1674 | names MUST match the supplied mailbox name pattern. A non-empty | ||
1675 | reference name argument is the name of a mailbox or a level of | ||
1676 | mailbox hierarchy, and indicates a context in which the mailbox | ||
1677 | name is interpreted in an implementation-defined manner. | ||
1678 | |||
1679 | |||
1680 | |||
1681 | |||
1682 | Crispin Standards Track [Page 30] | ||
1683 | |||
1684 | RFC 2060 IMAP4rev1 December 1996 | ||
1685 | |||
1686 | |||
1687 | An empty ("" string) mailbox name argument is a special request to | ||
1688 | return the hierarchy delimiter and the root name of the name given | ||
1689 | in the reference. The value returned as the root MAY be null if | ||
1690 | the reference is non-rooted or is null. In all cases, the | ||
1691 | hierarchy delimiter is returned. This permits a client to get the | ||
1692 | hierarchy delimiter even when no mailboxes by that name currently | ||
1693 | exist. | ||
1694 | |||
1695 | The reference and mailbox name arguments are interpreted, in an | ||
1696 | implementation-dependent fashion, into a canonical form that | ||
1697 | represents an unambiguous left-to-right hierarchy. The returned | ||
1698 | mailbox names will be in the interpreted form. | ||
1699 | |||
1700 | Any part of the reference argument that is included in the | ||
1701 | interpreted form SHOULD prefix the interpreted form. It SHOULD | ||
1702 | also be in the same form as the reference name argument. This | ||
1703 | rule permits the client to determine if the returned mailbox name | ||
1704 | is in the context of the reference argument, or if something about | ||
1705 | the mailbox argument overrode the reference argument. Without | ||
1706 | this rule, the client would have to have knowledge of the server's | ||
1707 | naming semantics including what characters are "breakouts" that | ||
1708 | override a naming context. | ||
1709 | |||
1710 | For example, here are some examples of how references and mailbox | ||
1711 | names might be interpreted on a UNIX-based server: | ||
1712 | |||
1713 | Reference Mailbox Name Interpretation | ||
1714 | ------------ ------------ -------------- | ||
1715 | ~smith/Mail/ foo.* ~smith/Mail/foo.* | ||
1716 | archive/ % archive/% | ||
1717 | #news. comp.mail.* #news.comp.mail.* | ||
1718 | ~smith/Mail/ /usr/doc/foo /usr/doc/foo | ||
1719 | archive/ ~fred/Mail/* ~fred/Mail/* | ||
1720 | |||
1721 | The first three examples demonstrate interpretations in the | ||
1722 | context of the reference argument. Note that "~smith/Mail" SHOULD | ||
1723 | NOT be transformed into something like "/u2/users/smith/Mail", or | ||
1724 | it would be impossible for the client to determine that the | ||
1725 | interpretation was in the context of the reference. | ||
1726 | |||
1727 | The character "*" is a wildcard, and matches zero or more | ||
1728 | characters at this position. The character "%" is similar to "*", | ||
1729 | but it does not match a hierarchy delimiter. If the "%" wildcard | ||
1730 | is the last character of a mailbox name argument, matching levels | ||
1731 | of hierarchy are also returned. If these levels of hierarchy are | ||
1732 | not also selectable mailboxes, they are returned with the | ||
1733 | \Noselect mailbox name attribute (see the description of the LIST | ||
1734 | response for more details). | ||
1735 | |||
1736 | |||
1737 | |||
1738 | Crispin Standards Track [Page 31] | ||
1739 | |||
1740 | RFC 2060 IMAP4rev1 December 1996 | ||
1741 | |||
1742 | |||
1743 | Server implementations are permitted to "hide" otherwise | ||
1744 | accessible mailboxes from the wildcard characters, by preventing | ||
1745 | certain characters or names from matching a wildcard in certain | ||
1746 | situations. For example, a UNIX-based server might restrict the | ||
1747 | interpretation of "*" so that an initial "/" character does not | ||
1748 | match. | ||
1749 | |||
1750 | The special name INBOX is included in the output from LIST, if | ||
1751 | INBOX is supported by this server for this user and if the | ||
1752 | uppercase string "INBOX" matches the interpreted reference and | ||
1753 | mailbox name arguments with wildcards as described above. The | ||
1754 | criteria for omitting INBOX is whether SELECT INBOX will return | ||
1755 | failure; it is not relevant whether the user's real INBOX resides | ||
1756 | on this or some other server. | ||
1757 | |||
1758 | Example: C: A101 LIST "" "" | ||
1759 | S: * LIST (\Noselect) "/" "" | ||
1760 | S: A101 OK LIST Completed | ||
1761 | C: A102 LIST #news.comp.mail.misc "" | ||
1762 | S: * LIST (\Noselect) "." #news. | ||
1763 | S: A102 OK LIST Completed | ||
1764 | C: A103 LIST /usr/staff/jones "" | ||
1765 | S: * LIST (\Noselect) "/" / | ||
1766 | S: A103 OK LIST Completed | ||
1767 | C: A202 LIST ~/Mail/ % | ||
1768 | S: * LIST (\Noselect) "/" ~/Mail/foo | ||
1769 | S: * LIST () "/" ~/Mail/meetings | ||
1770 | S: A202 OK LIST completed | ||
1771 | |||
1772 | 6.3.9. LSUB Command | ||
1773 | |||
1774 | Arguments: reference name | ||
1775 | mailbox name with possible wildcards | ||
1776 | |||
1777 | Responses: untagged responses: LSUB | ||
1778 | |||
1779 | Result: OK - lsub completed | ||
1780 | NO - lsub failure: can't list that reference or name | ||
1781 | BAD - command unknown or arguments invalid | ||
1782 | |||
1783 | The LSUB command returns a subset of names from the set of names | ||
1784 | that the user has declared as being "active" or "subscribed". | ||
1785 | Zero or more untagged LSUB replies are returned. The arguments to | ||
1786 | LSUB are in the same form as those for LIST. | ||
1787 | |||
1788 | A server MAY validate the subscribed names to see if they still | ||
1789 | exist. If a name does not exist, it SHOULD be flagged with the | ||
1790 | \Noselect attribute in the LSUB response. The server MUST NOT | ||
1791 | |||
1792 | |||
1793 | |||
1794 | Crispin Standards Track [Page 32] | ||
1795 | |||
1796 | RFC 2060 IMAP4rev1 December 1996 | ||
1797 | |||
1798 | |||
1799 | unilaterally remove an existing mailbox name from the subscription | ||
1800 | list even if a mailbox by that name no longer exists. | ||
1801 | |||
1802 | Example: C: A002 LSUB "#news." "comp.mail.*" | ||
1803 | S: * LSUB () "." #news.comp.mail.mime | ||
1804 | S: * LSUB () "." #news.comp.mail.misc | ||
1805 | S: A002 OK LSUB completed | ||
1806 | |||
1807 | 6.3.10. STATUS Command | ||
1808 | |||
1809 | Arguments: mailbox name | ||
1810 | status data item names | ||
1811 | |||
1812 | Responses: untagged responses: STATUS | ||
1813 | |||
1814 | Result: OK - status completed | ||
1815 | NO - status failure: no status for that name | ||
1816 | BAD - command unknown or arguments invalid | ||
1817 | |||
1818 | The STATUS command requests the status of the indicated mailbox. | ||
1819 | It does not change the currently selected mailbox, nor does it | ||
1820 | affect the state of any messages in the queried mailbox (in | ||
1821 | particular, STATUS MUST NOT cause messages to lose the \Recent | ||
1822 | flag). | ||
1823 | |||
1824 | The STATUS command provides an alternative to opening a second | ||
1825 | IMAP4rev1 connection and doing an EXAMINE command on a mailbox to | ||
1826 | query that mailbox's status without deselecting the current | ||
1827 | mailbox in the first IMAP4rev1 connection. | ||
1828 | |||
1829 | Unlike the LIST command, the STATUS command is not guaranteed to | ||
1830 | be fast in its response. In some implementations, the server is | ||
1831 | obliged to open the mailbox read-only internally to obtain certain | ||
1832 | status information. Also unlike the LIST command, the STATUS | ||
1833 | command does not accept wildcards. | ||
1834 | |||
1835 | The currently defined status data items that can be requested are: | ||
1836 | |||
1837 | MESSAGES The number of messages in the mailbox. | ||
1838 | |||
1839 | RECENT The number of messages with the \Recent flag set. | ||
1840 | |||
1841 | UIDNEXT The next UID value that will be assigned to a new | ||
1842 | message in the mailbox. It is guaranteed that this | ||
1843 | value will not change unless new messages are added | ||
1844 | to the mailbox; and that it will change when new | ||
1845 | messages are added even if those new messages are | ||
1846 | subsequently expunged. | ||
1847 | |||
1848 | |||
1849 | |||
1850 | Crispin Standards Track [Page 33] | ||
1851 | |||
1852 | RFC 2060 IMAP4rev1 December 1996 | ||
1853 | |||
1854 | |||
1855 | UIDVALIDITY The unique identifier validity value of the | ||
1856 | mailbox. | ||
1857 | |||
1858 | UNSEEN The number of messages which do not have the \Seen | ||
1859 | flag set. | ||
1860 | |||
1861 | |||
1862 | Example: C: A042 STATUS blurdybloop (UIDNEXT MESSAGES) | ||
1863 | S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292) | ||
1864 | S: A042 OK STATUS completed | ||
1865 | |||
1866 | 6.3.11. APPEND Command | ||
1867 | |||
1868 | Arguments: mailbox name | ||
1869 | OPTIONAL flag parenthesized list | ||
1870 | OPTIONAL date/time string | ||
1871 | message literal | ||
1872 | |||
1873 | Responses: no specific responses for this command | ||
1874 | |||
1875 | Result: OK - append completed | ||
1876 | NO - append error: can't append to that mailbox, error | ||
1877 | in flags or date/time or message text | ||
1878 | BAD - command unknown or arguments invalid | ||
1879 | |||
1880 | The APPEND command appends the literal argument as a new message | ||
1881 | to the end of the specified destination mailbox. This argument | ||
1882 | SHOULD be in the format of an [RFC-822] message. 8-bit characters | ||
1883 | are permitted in the message. A server implementation that is | ||
1884 | unable to preserve 8-bit data properly MUST be able to reversibly | ||
1885 | convert 8-bit APPEND data to 7-bit using a [MIME-IMB] content | ||
1886 | transfer encoding. | ||
1887 | |||
1888 | Note: There MAY be exceptions, e.g. draft messages, in which | ||
1889 | required [RFC-822] header lines are omitted in the message literal | ||
1890 | argument to APPEND. The full implications of doing so MUST be | ||
1891 | understood and carefully weighed. | ||
1892 | |||
1893 | If a flag parenthesized list is specified, the flags SHOULD be set in | ||
1894 | the resulting message; otherwise, the flag list of the resulting | ||
1895 | message is set empty by default. | ||
1896 | |||
1897 | If a date_time is specified, the internal date SHOULD be set in the | ||
1898 | resulting message; otherwise, the internal date of the resulting | ||
1899 | message is set to the current date and time by default. | ||
1900 | |||
1901 | |||
1902 | |||
1903 | |||
1904 | |||
1905 | |||
1906 | Crispin Standards Track [Page 34] | ||
1907 | |||
1908 | RFC 2060 IMAP4rev1 December 1996 | ||
1909 | |||
1910 | |||
1911 | If the append is unsuccessful for any reason, the mailbox MUST be | ||
1912 | restored to its state before the APPEND attempt; no partial appending | ||
1913 | is permitted. | ||
1914 | |||
1915 | If the destination mailbox does not exist, a server MUST return an | ||
1916 | error, and MUST NOT automatically create the mailbox. Unless it is | ||
1917 | certain that the destination mailbox can not be created, the server | ||
1918 | MUST send the response code "[TRYCREATE]" as the prefix of the text | ||
1919 | of the tagged NO response. This gives a hint to the client that it | ||
1920 | can attempt a CREATE command and retry the APPEND if the CREATE is | ||
1921 | successful. | ||
1922 | |||
1923 | If the mailbox is currently selected, the normal new mail actions | ||
1924 | SHOULD occur. Specifically, the server SHOULD notify the client | ||
1925 | immediately via an untagged EXISTS response. If the server does not | ||
1926 | do so, the client MAY issue a NOOP command (or failing that, a CHECK | ||
1927 | command) after one or more APPEND commands. | ||
1928 | |||
1929 | Example: C: A003 APPEND saved-messages (\Seen) {310} | ||
1930 | C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | ||
1931 | C: From: Fred Foobar <foobar@Blurdybloop.COM> | ||
1932 | C: Subject: afternoon meeting | ||
1933 | C: To: mooch@owatagu.siam.edu | ||
1934 | C: Message-Id: <B27397-0100000@Blurdybloop.COM> | ||
1935 | C: MIME-Version: 1.0 | ||
1936 | C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | ||
1937 | C: | ||
1938 | C: Hello Joe, do you think we can meet at 3:30 tomorrow? | ||
1939 | C: | ||
1940 | S: A003 OK APPEND completed | ||
1941 | |||
1942 | Note: the APPEND command is not used for message delivery, because | ||
1943 | it does not provide a mechanism to transfer [SMTP] envelope | ||
1944 | information. | ||
1945 | |||
1946 | 6.4. Client Commands - Selected State | ||
1947 | |||
1948 | In selected state, commands that manipulate messages in a mailbox are | ||
1949 | permitted. | ||
1950 | |||
1951 | In addition to the universal commands (CAPABILITY, NOOP, and LOGOUT), | ||
1952 | and the authenticated state commands (SELECT, EXAMINE, CREATE, | ||
1953 | DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE, LIST, LSUB, STATUS, and | ||
1954 | APPEND), the following commands are valid in the selected state: | ||
1955 | CHECK, CLOSE, EXPUNGE, SEARCH, FETCH, STORE, COPY, and UID. | ||
1956 | |||
1957 | |||
1958 | |||
1959 | |||
1960 | |||
1961 | |||
1962 | Crispin Standards Track [Page 35] | ||
1963 | |||
1964 | RFC 2060 IMAP4rev1 December 1996 | ||
1965 | |||
1966 | |||
1967 | 6.4.1. CHECK Command | ||
1968 | |||
1969 | Arguments: none | ||
1970 | |||
1971 | Responses: no specific responses for this command | ||
1972 | |||
1973 | Result: OK - check completed | ||
1974 | BAD - command unknown or arguments invalid | ||
1975 | |||
1976 | The CHECK command requests a checkpoint of the currently selected | ||
1977 | mailbox. A checkpoint refers to any implementation-dependent | ||
1978 | housekeeping associated with the mailbox (e.g. resolving the | ||
1979 | server's in-memory state of the mailbox with the state on its | ||
1980 | disk) that is not normally executed as part of each command. A | ||
1981 | checkpoint MAY take a non-instantaneous amount of real time to | ||
1982 | complete. If a server implementation has no such housekeeping | ||
1983 | considerations, CHECK is equivalent to NOOP. | ||
1984 | |||
1985 | There is no guarantee that an EXISTS untagged response will happen | ||
1986 | as a result of CHECK. NOOP, not CHECK, SHOULD be used for new | ||
1987 | mail polling. | ||
1988 | |||
1989 | Example: C: FXXZ CHECK | ||
1990 | S: FXXZ OK CHECK Completed | ||
1991 | |||
1992 | 6.4.2. CLOSE Command | ||
1993 | |||
1994 | Arguments: none | ||
1995 | |||
1996 | Responses: no specific responses for this command | ||
1997 | |||
1998 | Result: OK - close completed, now in authenticated state | ||
1999 | NO - close failure: no mailbox selected | ||
2000 | BAD - command unknown or arguments invalid | ||
2001 | |||
2002 | The CLOSE command permanently removes from the currently selected | ||
2003 | mailbox all messages that have the \Deleted flag set, and returns | ||
2004 | to authenticated state from selected state. No untagged EXPUNGE | ||
2005 | responses are sent. | ||
2006 | |||
2007 | No messages are removed, and no error is given, if the mailbox is | ||
2008 | selected by an EXAMINE command or is otherwise selected read-only. | ||
2009 | |||
2010 | Even if a mailbox is selected, a SELECT, EXAMINE, or LOGOUT | ||
2011 | command MAY be issued without previously issuing a CLOSE command. | ||
2012 | The SELECT, EXAMINE, and LOGOUT commands implicitly close the | ||
2013 | currently selected mailbox without doing an expunge. However, | ||
2014 | when many messages are deleted, a CLOSE-LOGOUT or CLOSE-SELECT | ||
2015 | |||
2016 | |||
2017 | |||
2018 | Crispin Standards Track [Page 36] | ||
2019 | |||
2020 | RFC 2060 IMAP4rev1 December 1996 | ||
2021 | |||
2022 | |||
2023 | sequence is considerably faster than an EXPUNGE-LOGOUT or | ||
2024 | EXPUNGE-SELECT because no untagged EXPUNGE responses (which the | ||
2025 | client would probably ignore) are sent. | ||
2026 | |||
2027 | Example: C: A341 CLOSE | ||
2028 | S: A341 OK CLOSE completed | ||
2029 | |||
2030 | 6.4.3. EXPUNGE Command | ||
2031 | |||
2032 | Arguments: none | ||
2033 | |||
2034 | Responses: untagged responses: EXPUNGE | ||
2035 | |||
2036 | Result: OK - expunge completed | ||
2037 | NO - expunge failure: can't expunge (e.g. permission | ||
2038 | denied) | ||
2039 | BAD - command unknown or arguments invalid | ||
2040 | |||
2041 | The EXPUNGE command permanently removes from the currently | ||
2042 | selected mailbox all messages that have the \Deleted flag set. | ||
2043 | Before returning an OK to the client, an untagged EXPUNGE response | ||
2044 | is sent for each message that is removed. | ||
2045 | |||
2046 | Example: C: A202 EXPUNGE | ||
2047 | S: * 3 EXPUNGE | ||
2048 | S: * 3 EXPUNGE | ||
2049 | S: * 5 EXPUNGE | ||
2050 | S: * 8 EXPUNGE | ||
2051 | S: A202 OK EXPUNGE completed | ||
2052 | |||
2053 | Note: in this example, messages 3, 4, 7, and 11 had the | ||
2054 | \Deleted flag set. See the description of the EXPUNGE | ||
2055 | response for further explanation. | ||
2056 | |||
2057 | 6.4.4. SEARCH Command | ||
2058 | |||
2059 | Arguments: OPTIONAL [CHARSET] specification | ||
2060 | searching criteria (one or more) | ||
2061 | |||
2062 | Responses: REQUIRED untagged response: SEARCH | ||
2063 | |||
2064 | Result: OK - search completed | ||
2065 | NO - search error: can't search that [CHARSET] or | ||
2066 | criteria | ||
2067 | BAD - command unknown or arguments invalid | ||
2068 | |||
2069 | |||
2070 | |||
2071 | |||
2072 | |||
2073 | |||
2074 | Crispin Standards Track [Page 37] | ||
2075 | |||
2076 | RFC 2060 IMAP4rev1 December 1996 | ||
2077 | |||
2078 | |||
2079 | The SEARCH command searches the mailbox for messages that match | ||
2080 | the given searching criteria. Searching criteria consist of one | ||
2081 | or more search keys. The untagged SEARCH response from the server | ||
2082 | contains a listing of message sequence numbers corresponding to | ||
2083 | those messages that match the searching criteria. | ||
2084 | |||
2085 | When multiple keys are specified, the result is the intersection | ||
2086 | (AND function) of all the messages that match those keys. For | ||
2087 | example, the criteria DELETED FROM "SMITH" SINCE 1-Feb-1994 refers | ||
2088 | to all deleted messages from Smith that were placed in the mailbox | ||
2089 | since February 1, 1994. A search key can also be a parenthesized | ||
2090 | list of one or more search keys (e.g. for use with the OR and NOT | ||
2091 | keys). | ||
2092 | |||
2093 | Server implementations MAY exclude [MIME-IMB] body parts with | ||
2094 | terminal content media types other than TEXT and MESSAGE from | ||
2095 | consideration in SEARCH matching. | ||
2096 | |||
2097 | The OPTIONAL [CHARSET] specification consists of the word | ||
2098 | "CHARSET" followed by a registered [CHARSET]. It indicates the | ||
2099 | [CHARSET] of the strings that appear in the search criteria. | ||
2100 | [MIME-IMB] content transfer encodings, and [MIME-HDRS] strings in | ||
2101 | [RFC-822]/[MIME-IMB] headers, MUST be decoded before comparing | ||
2102 | text in a [CHARSET] other than US-ASCII. US-ASCII MUST be | ||
2103 | supported; other [CHARSET]s MAY be supported. If the server does | ||
2104 | not support the specified [CHARSET], it MUST return a tagged NO | ||
2105 | response (not a BAD). | ||
2106 | |||
2107 | In all search keys that use strings, a message matches the key if | ||
2108 | the string is a substring of the field. The matching is case- | ||
2109 | insensitive. | ||
2110 | |||
2111 | The defined search keys are as follows. Refer to the Formal | ||
2112 | Syntax section for the precise syntactic definitions of the | ||
2113 | arguments. | ||
2114 | |||
2115 | <message set> Messages with message sequence numbers | ||
2116 | corresponding to the specified message sequence | ||
2117 | number set | ||
2118 | |||
2119 | ALL All messages in the mailbox; the default initial | ||
2120 | key for ANDing. | ||
2121 | |||
2122 | ANSWERED Messages with the \Answered flag set. | ||
2123 | |||
2124 | BCC <string> Messages that contain the specified string in the | ||
2125 | envelope structure's BCC field. | ||
2126 | |||
2127 | |||
2128 | |||
2129 | |||
2130 | Crispin Standards Track [Page 38] | ||
2131 | |||
2132 | RFC 2060 IMAP4rev1 December 1996 | ||
2133 | |||
2134 | |||
2135 | BEFORE <date> Messages whose internal date is earlier than the | ||
2136 | specified date. | ||
2137 | |||
2138 | BODY <string> Messages that contain the specified string in the | ||
2139 | body of the message. | ||
2140 | |||
2141 | CC <string> Messages that contain the specified string in the | ||
2142 | envelope structure's CC field. | ||
2143 | |||
2144 | DELETED Messages with the \Deleted flag set. | ||
2145 | |||
2146 | DRAFT Messages with the \Draft flag set. | ||
2147 | |||
2148 | FLAGGED Messages with the \Flagged flag set. | ||
2149 | |||
2150 | FROM <string> Messages that contain the specified string in the | ||
2151 | envelope structure's FROM field. | ||
2152 | |||
2153 | HEADER <field-name> <string> | ||
2154 | Messages that have a header with the specified | ||
2155 | field-name (as defined in [RFC-822]) and that | ||
2156 | contains the specified string in the [RFC-822] | ||
2157 | field-body. | ||
2158 | |||
2159 | KEYWORD <flag> Messages with the specified keyword set. | ||
2160 | |||
2161 | LARGER <n> Messages with an [RFC-822] size larger than the | ||
2162 | specified number of octets. | ||
2163 | |||
2164 | NEW Messages that have the \Recent flag set but not the | ||
2165 | \Seen flag. This is functionally equivalent to | ||
2166 | "(RECENT UNSEEN)". | ||
2167 | |||
2168 | NOT <search-key> | ||
2169 | Messages that do not match the specified search | ||
2170 | key. | ||
2171 | |||
2172 | OLD Messages that do not have the \Recent flag set. | ||
2173 | This is functionally equivalent to "NOT RECENT" (as | ||
2174 | opposed to "NOT NEW"). | ||
2175 | |||
2176 | ON <date> Messages whose internal date is within the | ||
2177 | specified date. | ||
2178 | |||
2179 | OR <search-key1> <search-key2> | ||
2180 | Messages that match either search key. | ||
2181 | |||
2182 | RECENT Messages that have the \Recent flag set. | ||
2183 | |||
2184 | |||
2185 | |||
2186 | Crispin Standards Track [Page 39] | ||
2187 | |||
2188 | RFC 2060 IMAP4rev1 December 1996 | ||
2189 | |||
2190 | |||
2191 | SEEN Messages that have the \Seen flag set. | ||
2192 | |||
2193 | SENTBEFORE <date> | ||
2194 | Messages whose [RFC-822] Date: header is earlier | ||
2195 | than the specified date. | ||
2196 | |||
2197 | SENTON <date> Messages whose [RFC-822] Date: header is within the | ||
2198 | specified date. | ||
2199 | |||
2200 | SENTSINCE <date> | ||
2201 | Messages whose [RFC-822] Date: header is within or | ||
2202 | later than the specified date. | ||
2203 | |||
2204 | SINCE <date> Messages whose internal date is within or later | ||
2205 | than the specified date. | ||
2206 | |||
2207 | SMALLER <n> Messages with an [RFC-822] size smaller than the | ||
2208 | specified number of octets. | ||
2209 | |||
2210 | SUBJECT <string> | ||
2211 | Messages that contain the specified string in the | ||
2212 | envelope structure's SUBJECT field. | ||
2213 | |||
2214 | TEXT <string> Messages that contain the specified string in the | ||
2215 | header or body of the message. | ||
2216 | |||
2217 | TO <string> Messages that contain the specified string in the | ||
2218 | envelope structure's TO field. | ||
2219 | |||
2220 | UID <message set> | ||
2221 | Messages with unique identifiers corresponding to | ||
2222 | the specified unique identifier set. | ||
2223 | |||
2224 | UNANSWERED Messages that do not have the \Answered flag set. | ||
2225 | |||
2226 | UNDELETED Messages that do not have the \Deleted flag set. | ||
2227 | |||
2228 | UNDRAFT Messages that do not have the \Draft flag set. | ||
2229 | |||
2230 | UNFLAGGED Messages that do not have the \Flagged flag set. | ||
2231 | |||
2232 | UNKEYWORD <flag> | ||
2233 | Messages that do not have the specified keyword | ||
2234 | set. | ||
2235 | |||
2236 | UNSEEN Messages that do not have the \Seen flag set. | ||
2237 | |||
2238 | |||
2239 | |||
2240 | |||
2241 | |||
2242 | Crispin Standards Track [Page 40] | ||
2243 | |||
2244 | RFC 2060 IMAP4rev1 December 1996 | ||
2245 | |||
2246 | |||
2247 | Example: C: A282 SEARCH FLAGGED SINCE 1-Feb-1994 NOT FROM "Smith" | ||
2248 | S: * SEARCH 2 84 882 | ||
2249 | S: A282 OK SEARCH completed | ||
2250 | |||
2251 | 6.4.5. FETCH Command | ||
2252 | |||
2253 | Arguments: message set | ||
2254 | message data item names | ||
2255 | |||
2256 | Responses: untagged responses: FETCH | ||
2257 | |||
2258 | Result: OK - fetch completed | ||
2259 | NO - fetch error: can't fetch that data | ||
2260 | BAD - command unknown or arguments invalid | ||
2261 | |||
2262 | The FETCH command retrieves data associated with a message in the | ||
2263 | mailbox. The data items to be fetched can be either a single atom | ||
2264 | or a parenthesized list. | ||
2265 | |||
2266 | The currently defined data items that can be fetched are: | ||
2267 | |||
2268 | ALL Macro equivalent to: (FLAGS INTERNALDATE | ||
2269 | RFC822.SIZE ENVELOPE) | ||
2270 | |||
2271 | BODY Non-extensible form of BODYSTRUCTURE. | ||
2272 | |||
2273 | BODY[<section>]<<partial>> | ||
2274 | The text of a particular body section. The section | ||
2275 | specification is a set of zero or more part | ||
2276 | specifiers delimited by periods. A part specifier | ||
2277 | is either a part number or one of the following: | ||
2278 | HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, and | ||
2279 | TEXT. An empty section specification refers to the | ||
2280 | entire message, including the header. | ||
2281 | |||
2282 | Every message has at least one part number. | ||
2283 | Non-[MIME-IMB] messages, and non-multipart | ||
2284 | [MIME-IMB] messages with no encapsulated message, | ||
2285 | only have a part 1. | ||
2286 | |||
2287 | Multipart messages are assigned consecutive part | ||
2288 | numbers, as they occur in the message. If a | ||
2289 | particular part is of type message or multipart, | ||
2290 | its parts MUST be indicated by a period followed by | ||
2291 | the part number within that nested multipart part. | ||
2292 | |||
2293 | |||
2294 | |||
2295 | |||
2296 | |||
2297 | |||
2298 | Crispin Standards Track [Page 41] | ||
2299 | |||
2300 | RFC 2060 IMAP4rev1 December 1996 | ||
2301 | |||
2302 | |||
2303 | A part of type MESSAGE/RFC822 also has nested part | ||
2304 | numbers, referring to parts of the MESSAGE part's | ||
2305 | body. | ||
2306 | |||
2307 | The HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, and | ||
2308 | TEXT part specifiers can be the sole part specifier | ||
2309 | or can be prefixed by one or more numeric part | ||
2310 | specifiers, provided that the numeric part | ||
2311 | specifier refers to a part of type MESSAGE/RFC822. | ||
2312 | The MIME part specifier MUST be prefixed by one or | ||
2313 | more numeric part specifiers. | ||
2314 | |||
2315 | The HEADER, HEADER.FIELDS, and HEADER.FIELDS.NOT | ||
2316 | part specifiers refer to the [RFC-822] header of | ||
2317 | the message or of an encapsulated [MIME-IMT] | ||
2318 | MESSAGE/RFC822 message. HEADER.FIELDS and | ||
2319 | HEADER.FIELDS.NOT are followed by a list of | ||
2320 | field-name (as defined in [RFC-822]) names, and | ||
2321 | return a subset of the header. The subset returned | ||
2322 | by HEADER.FIELDS contains only those header fields | ||
2323 | with a field-name that matches one of the names in | ||
2324 | the list; similarly, the subset returned by | ||
2325 | HEADER.FIELDS.NOT contains only the header fields | ||
2326 | with a non-matching field-name. The field-matching | ||
2327 | is case-insensitive but otherwise exact. In all | ||
2328 | cases, the delimiting blank line between the header | ||
2329 | and the body is always included. | ||
2330 | |||
2331 | The MIME part specifier refers to the [MIME-IMB] | ||
2332 | header for this part. | ||
2333 | |||
2334 | The TEXT part specifier refers to the text body of | ||
2335 | the message, omitting the [RFC-822] header. | ||
2336 | |||
2337 | |||
2338 | |||
2339 | |||
2340 | |||
2341 | |||
2342 | |||
2343 | |||
2344 | |||
2345 | |||
2346 | |||
2347 | |||
2348 | |||
2349 | |||
2350 | |||
2351 | |||
2352 | |||
2353 | |||
2354 | Crispin Standards Track [Page 42] | ||
2355 | |||
2356 | RFC 2060 IMAP4rev1 December 1996 | ||
2357 | |||
2358 | |||
2359 | Here is an example of a complex message | ||
2360 | with some of its part specifiers: | ||
2361 | |||
2362 | HEADER ([RFC-822] header of the message) | ||
2363 | TEXT MULTIPART/MIXED | ||
2364 | 1 TEXT/PLAIN | ||
2365 | 2 APPLICATION/OCTET-STREAM | ||
2366 | 3 MESSAGE/RFC822 | ||
2367 | 3.HEADER ([RFC-822] header of the message) | ||
2368 | 3.TEXT ([RFC-822] text body of the message) | ||
2369 | 3.1 TEXT/PLAIN | ||
2370 | 3.2 APPLICATION/OCTET-STREAM | ||
2371 | 4 MULTIPART/MIXED | ||
2372 | 4.1 IMAGE/GIF | ||
2373 | 4.1.MIME ([MIME-IMB] header for the IMAGE/GIF) | ||
2374 | 4.2 MESSAGE/RFC822 | ||
2375 | 4.2.HEADER ([RFC-822] header of the message) | ||
2376 | 4.2.TEXT ([RFC-822] text body of the message) | ||
2377 | 4.2.1 TEXT/PLAIN | ||
2378 | 4.2.2 MULTIPART/ALTERNATIVE | ||
2379 | 4.2.2.1 TEXT/PLAIN | ||
2380 | 4.2.2.2 TEXT/RICHTEXT | ||
2381 | |||
2382 | |||
2383 | It is possible to fetch a substring of the | ||
2384 | designated text. This is done by appending an open | ||
2385 | angle bracket ("<"), the octet position of the | ||
2386 | first desired octet, a period, the maximum number | ||
2387 | of octets desired, and a close angle bracket (">") | ||
2388 | to the part specifier. If the starting octet is | ||
2389 | beyond the end of the text, an empty string is | ||
2390 | returned. | ||
2391 | |||
2392 | Any partial fetch that attempts to read beyond the | ||
2393 | end of the text is truncated as appropriate. A | ||
2394 | partial fetch that starts at octet 0 is returned as | ||
2395 | a partial fetch, even if this truncation happened. | ||
2396 | |||
2397 | Note: this means that BODY[]<0.2048> of a | ||
2398 | 1500-octet message will return BODY[]<0> | ||
2399 | with a literal of size 1500, not BODY[]. | ||
2400 | |||
2401 | Note: a substring fetch of a | ||
2402 | HEADER.FIELDS or HEADER.FIELDS.NOT part | ||
2403 | specifier is calculated after subsetting | ||
2404 | the header. | ||
2405 | |||
2406 | |||
2407 | |||
2408 | |||
2409 | |||
2410 | Crispin Standards Track [Page 43] | ||
2411 | |||
2412 | RFC 2060 IMAP4rev1 December 1996 | ||
2413 | |||
2414 | |||
2415 | The \Seen flag is implicitly set; if this causes | ||
2416 | the flags to change they SHOULD be included as part | ||
2417 | of the FETCH responses. | ||
2418 | |||
2419 | BODY.PEEK[<section>]<<partial>> | ||
2420 | An alternate form of BODY[<section>] that does not | ||
2421 | implicitly set the \Seen flag. | ||
2422 | |||
2423 | BODYSTRUCTURE The [MIME-IMB] body structure of the message. This | ||
2424 | is computed by the server by parsing the [MIME-IMB] | ||
2425 | header fields in the [RFC-822] header and | ||
2426 | [MIME-IMB] headers. | ||
2427 | |||
2428 | ENVELOPE The envelope structure of the message. This is | ||
2429 | computed by the server by parsing the [RFC-822] | ||
2430 | header into the component parts, defaulting various | ||
2431 | fields as necessary. | ||
2432 | |||
2433 | FAST Macro equivalent to: (FLAGS INTERNALDATE | ||
2434 | RFC822.SIZE) | ||
2435 | |||
2436 | FLAGS The flags that are set for this message. | ||
2437 | |||
2438 | FULL Macro equivalent to: (FLAGS INTERNALDATE | ||
2439 | RFC822.SIZE ENVELOPE BODY) | ||
2440 | |||
2441 | INTERNALDATE The internal date of the message. | ||
2442 | |||
2443 | RFC822 Functionally equivalent to BODY[], differing in the | ||
2444 | syntax of the resulting untagged FETCH data (RFC822 | ||
2445 | is returned). | ||
2446 | |||
2447 | RFC822.HEADER Functionally equivalent to BODY.PEEK[HEADER], | ||
2448 | differing in the syntax of the resulting untagged | ||
2449 | FETCH data (RFC822.HEADER is returned). | ||
2450 | |||
2451 | RFC822.SIZE The [RFC-822] size of the message. | ||
2452 | |||
2453 | RFC822.TEXT Functionally equivalent to BODY[TEXT], differing in | ||
2454 | the syntax of the resulting untagged FETCH data | ||
2455 | (RFC822.TEXT is returned). | ||
2456 | |||
2457 | UID The unique identifier for the message. | ||
2458 | |||
2459 | |||
2460 | |||
2461 | |||
2462 | |||
2463 | |||
2464 | |||
2465 | |||
2466 | Crispin Standards Track [Page 44] | ||
2467 | |||
2468 | RFC 2060 IMAP4rev1 December 1996 | ||
2469 | |||
2470 | |||
2471 | Example: C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)]) | ||
2472 | S: * 2 FETCH .... | ||
2473 | S: * 3 FETCH .... | ||
2474 | S: * 4 FETCH .... | ||
2475 | S: A654 OK FETCH completed | ||
2476 | |||
2477 | 6.4.6. STORE Command | ||
2478 | |||
2479 | Arguments: message set | ||
2480 | message data item name | ||
2481 | value for message data item | ||
2482 | |||
2483 | Responses: untagged responses: FETCH | ||
2484 | |||
2485 | Result: OK - store completed | ||
2486 | NO - store error: can't store that data | ||
2487 | BAD - command unknown or arguments invalid | ||
2488 | |||
2489 | The STORE command alters data associated with a message in the | ||
2490 | mailbox. Normally, STORE will return the updated value of the | ||
2491 | data with an untagged FETCH response. A suffix of ".SILENT" in | ||
2492 | the data item name prevents the untagged FETCH, and the server | ||
2493 | SHOULD assume that the client has determined the updated value | ||
2494 | itself or does not care about the updated value. | ||
2495 | |||
2496 | Note: regardless of whether or not the ".SILENT" suffix was | ||
2497 | used, the server SHOULD send an untagged FETCH response if a | ||
2498 | change to a message's flags from an external source is | ||
2499 | observed. The intent is that the status of the flags is | ||
2500 | determinate without a race condition. | ||
2501 | |||
2502 | The currently defined data items that can be stored are: | ||
2503 | |||
2504 | FLAGS <flag list> | ||
2505 | Replace the flags for the message with the | ||
2506 | argument. The new value of the flags are returned | ||
2507 | as if a FETCH of those flags was done. | ||
2508 | |||
2509 | FLAGS.SILENT <flag list> | ||
2510 | Equivalent to FLAGS, but without returning a new | ||
2511 | value. | ||
2512 | |||
2513 | +FLAGS <flag list> | ||
2514 | Add the argument to the flags for the message. The | ||
2515 | new value of the flags are returned as if a FETCH | ||
2516 | of those flags was done. | ||
2517 | |||
2518 | |||
2519 | |||
2520 | |||
2521 | |||
2522 | Crispin Standards Track [Page 45] | ||
2523 | |||
2524 | RFC 2060 IMAP4rev1 December 1996 | ||
2525 | |||
2526 | |||
2527 | +FLAGS.SILENT <flag list> | ||
2528 | Equivalent to +FLAGS, but without returning a new | ||
2529 | value. | ||
2530 | |||
2531 | -FLAGS <flag list> | ||
2532 | Remove the argument from the flags for the message. | ||
2533 | The new value of the flags are returned as if a | ||
2534 | FETCH of those flags was done. | ||
2535 | |||
2536 | -FLAGS.SILENT <flag list> | ||
2537 | Equivalent to -FLAGS, but without returning a new | ||
2538 | value. | ||
2539 | |||
2540 | Example: C: A003 STORE 2:4 +FLAGS (\Deleted) | ||
2541 | S: * 2 FETCH FLAGS (\Deleted \Seen) | ||
2542 | S: * 3 FETCH FLAGS (\Deleted) | ||
2543 | S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen) | ||
2544 | S: A003 OK STORE completed | ||
2545 | |||
2546 | 6.4.7. COPY Command | ||
2547 | |||
2548 | Arguments: message set | ||
2549 | mailbox name | ||
2550 | |||
2551 | Responses: no specific responses for this command | ||
2552 | |||
2553 | Result: OK - copy completed | ||
2554 | NO - copy error: can't copy those messages or to that | ||
2555 | name | ||
2556 | BAD - command unknown or arguments invalid | ||
2557 | |||
2558 | The COPY command copies the specified message(s) to the end of the | ||
2559 | specified destination mailbox. The flags and internal date of the | ||
2560 | message(s) SHOULD be preserved in the copy. | ||
2561 | |||
2562 | If the destination mailbox does not exist, a server SHOULD return | ||
2563 | an error. It SHOULD NOT automatically create the mailbox. Unless | ||
2564 | it is certain that the destination mailbox can not be created, the | ||
2565 | server MUST send the response code "[TRYCREATE]" as the prefix of | ||
2566 | the text of the tagged NO response. This gives a hint to the | ||
2567 | client that it can attempt a CREATE command and retry the COPY if | ||
2568 | the CREATE is successful. | ||
2569 | |||
2570 | |||
2571 | |||
2572 | |||
2573 | |||
2574 | |||
2575 | |||
2576 | |||
2577 | |||
2578 | Crispin Standards Track [Page 46] | ||
2579 | |||
2580 | RFC 2060 IMAP4rev1 December 1996 | ||
2581 | |||
2582 | |||
2583 | If the COPY command is unsuccessful for any reason, server | ||
2584 | implementations MUST restore the destination mailbox to its state | ||
2585 | before the COPY attempt. | ||
2586 | |||
2587 | Example: C: A003 COPY 2:4 MEETING | ||
2588 | S: A003 OK COPY completed | ||
2589 | |||
2590 | 6.4.8. UID Command | ||
2591 | |||
2592 | Arguments: command name | ||
2593 | command arguments | ||
2594 | |||
2595 | Responses: untagged responses: FETCH, SEARCH | ||
2596 | |||
2597 | Result: OK - UID command completed | ||
2598 | NO - UID command error | ||
2599 | BAD - command unknown or arguments invalid | ||
2600 | |||
2601 | The UID command has two forms. In the first form, it takes as its | ||
2602 | arguments a COPY, FETCH, or STORE command with arguments | ||
2603 | appropriate for the associated command. However, the numbers in | ||
2604 | the message set argument are unique identifiers instead of message | ||
2605 | sequence numbers. | ||
2606 | |||
2607 | In the second form, the UID command takes a SEARCH command with | ||
2608 | SEARCH command arguments. The interpretation of the arguments is | ||
2609 | the same as with SEARCH; however, the numbers returned in a SEARCH | ||
2610 | response for a UID SEARCH command are unique identifiers instead | ||
2611 | of message sequence numbers. For example, the command UID SEARCH | ||
2612 | 1:100 UID 443:557 returns the unique identifiers corresponding to | ||
2613 | the intersection of the message sequence number set 1:100 and the | ||
2614 | UID set 443:557. | ||
2615 | |||
2616 | Message set ranges are permitted; however, there is no guarantee | ||
2617 | that unique identifiers be contiguous. A non-existent unique | ||
2618 | identifier within a message set range is ignored without any error | ||
2619 | message generated. | ||
2620 | |||
2621 | The number after the "*" in an untagged FETCH response is always a | ||
2622 | message sequence number, not a unique identifier, even for a UID | ||
2623 | command response. However, server implementations MUST implicitly | ||
2624 | include the UID message data item as part of any FETCH response | ||
2625 | caused by a UID command, regardless of whether a UID was specified | ||
2626 | as a message data item to the FETCH. | ||
2627 | |||
2628 | |||
2629 | |||
2630 | |||
2631 | |||
2632 | |||
2633 | |||
2634 | Crispin Standards Track [Page 47] | ||
2635 | |||
2636 | RFC 2060 IMAP4rev1 December 1996 | ||
2637 | |||
2638 | |||
2639 | Example: C: A999 UID FETCH 4827313:4828442 FLAGS | ||
2640 | S: * 23 FETCH (FLAGS (\Seen) UID 4827313) | ||
2641 | S: * 24 FETCH (FLAGS (\Seen) UID 4827943) | ||
2642 | S: * 25 FETCH (FLAGS (\Seen) UID 4828442) | ||
2643 | S: A999 UID FETCH completed | ||
2644 | |||
2645 | 6.5. Client Commands - Experimental/Expansion | ||
2646 | |||
2647 | 6.5.1. X<atom> Command | ||
2648 | |||
2649 | Arguments: implementation defined | ||
2650 | |||
2651 | Responses: implementation defined | ||
2652 | |||
2653 | Result: OK - command completed | ||
2654 | NO - failure | ||
2655 | BAD - command unknown or arguments invalid | ||
2656 | |||
2657 | Any command prefixed with an X is an experimental command. | ||
2658 | Commands which are not part of this specification, a standard or | ||
2659 | standards-track revision of this specification, or an IESG- | ||
2660 | approved experimental protocol, MUST use the X prefix. | ||
2661 | |||
2662 | Any added untagged responses issued by an experimental command | ||
2663 | MUST also be prefixed with an X. Server implementations MUST NOT | ||
2664 | send any such untagged responses, unless the client requested it | ||
2665 | by issuing the associated experimental command. | ||
2666 | |||
2667 | Example: C: a441 CAPABILITY | ||
2668 | S: * CAPABILITY IMAP4rev1 AUTH=KERBEROS_V4 XPIG-LATIN | ||
2669 | S: a441 OK CAPABILITY completed | ||
2670 | C: A442 XPIG-LATIN | ||
2671 | S: * XPIG-LATIN ow-nay eaking-spay ig-pay atin-lay | ||
2672 | S: A442 OK XPIG-LATIN ompleted-cay | ||
2673 | |||
2674 | 7. Server Responses | ||
2675 | |||
2676 | Server responses are in three forms: status responses, server data, | ||
2677 | and command continuation request. The information contained in a | ||
2678 | server response, identified by "Contents:" in the response | ||
2679 | descriptions below, is described by function, not by syntax. The | ||
2680 | precise syntax of server responses is described in the Formal Syntax | ||
2681 | section. | ||
2682 | |||
2683 | The client MUST be prepared to accept any response at all times. | ||
2684 | |||
2685 | |||
2686 | |||
2687 | |||
2688 | |||
2689 | |||
2690 | Crispin Standards Track [Page 48] | ||
2691 | |||
2692 | RFC 2060 IMAP4rev1 December 1996 | ||
2693 | |||
2694 | |||
2695 | Status responses can be tagged or untagged. Tagged status responses | ||
2696 | indicate the completion result (OK, NO, or BAD status) of a client | ||
2697 | command, and have a tag matching the command. | ||
2698 | |||
2699 | Some status responses, and all server data, are untagged. An | ||
2700 | untagged response is indicated by the token "*" instead of a tag. | ||
2701 | Untagged status responses indicate server greeting, or server status | ||
2702 | that does not indicate the completion of a command (for example, an | ||
2703 | impending system shutdown alert). For historical reasons, untagged | ||
2704 | server data responses are also called "unsolicited data", although | ||
2705 | strictly speaking only unilateral server data is truly "unsolicited". | ||
2706 | |||
2707 | Certain server data MUST be recorded by the client when it is | ||
2708 | received; this is noted in the description of that data. Such data | ||
2709 | conveys critical information which affects the interpretation of all | ||
2710 | subsequent commands and responses (e.g. updates reflecting the | ||
2711 | creation or destruction of messages). | ||
2712 | |||
2713 | Other server data SHOULD be recorded for later reference; if the | ||
2714 | client does not need to record the data, or if recording the data has | ||
2715 | no obvious purpose (e.g. a SEARCH response when no SEARCH command is | ||
2716 | in progress), the data SHOULD be ignored. | ||
2717 | |||
2718 | An example of unilateral untagged server data occurs when the IMAP | ||
2719 | connection is in selected state. In selected state, the server | ||
2720 | checks the mailbox for new messages as part of command execution. | ||
2721 | Normally, this is part of the execution of every command; hence, a | ||
2722 | NOOP command suffices to check for new messages. If new messages are | ||
2723 | found, the server sends untagged EXISTS and RECENT responses | ||
2724 | reflecting the new size of the mailbox. Server implementations that | ||
2725 | offer multiple simultaneous access to the same mailbox SHOULD also | ||
2726 | send appropriate unilateral untagged FETCH and EXPUNGE responses if | ||
2727 | another agent changes the state of any message flags or expunges any | ||
2728 | messages. | ||
2729 | |||
2730 | Command continuation request responses use the token "+" instead of a | ||
2731 | tag. These responses are sent by the server to indicate acceptance | ||
2732 | of an incomplete client command and readiness for the remainder of | ||
2733 | the command. | ||
2734 | |||
2735 | 7.1. Server Responses - Status Responses | ||
2736 | |||
2737 | Status responses are OK, NO, BAD, PREAUTH and BYE. OK, NO, and BAD | ||
2738 | may be tagged or untagged. PREAUTH and BYE are always untagged. | ||
2739 | |||
2740 | Status responses MAY include an OPTIONAL "response code". A response | ||
2741 | code consists of data inside square brackets in the form of an atom, | ||
2742 | possibly followed by a space and arguments. The response code | ||
2743 | |||
2744 | |||
2745 | |||
2746 | Crispin Standards Track [Page 49] | ||
2747 | |||
2748 | RFC 2060 IMAP4rev1 December 1996 | ||
2749 | |||
2750 | |||
2751 | contains additional information or status codes for client software | ||
2752 | beyond the OK/NO/BAD condition, and are defined when there is a | ||
2753 | specific action that a client can take based upon the additional | ||
2754 | information. | ||
2755 | |||
2756 | The currently defined response codes are: | ||
2757 | |||
2758 | ALERT The human-readable text contains a special alert | ||
2759 | that MUST be presented to the user in a fashion | ||
2760 | that calls the user's attention to the message. | ||
2761 | |||
2762 | NEWNAME Followed by a mailbox name and a new mailbox name. | ||
2763 | A SELECT or EXAMINE is failing because the target | ||
2764 | mailbox name no longer exists because it was | ||
2765 | renamed to the new mailbox name. This is a hint to | ||
2766 | the client that the operation can succeed if the | ||
2767 | SELECT or EXAMINE is reissued with the new mailbox | ||
2768 | name. | ||
2769 | |||
2770 | PARSE The human-readable text represents an error in | ||
2771 | parsing the [RFC-822] header or [MIME-IMB] headers | ||
2772 | of a message in the mailbox. | ||
2773 | |||
2774 | PERMANENTFLAGS Followed by a parenthesized list of flags, | ||
2775 | indicates which of the known flags that the client | ||
2776 | can change permanently. Any flags that are in the | ||
2777 | FLAGS untagged response, but not the PERMANENTFLAGS | ||
2778 | list, can not be set permanently. If the client | ||
2779 | attempts to STORE a flag that is not in the | ||
2780 | PERMANENTFLAGS list, the server will either reject | ||
2781 | it with a NO reply or store the state for the | ||
2782 | remainder of the current session only. The | ||
2783 | PERMANENTFLAGS list can also include the special | ||
2784 | flag \*, which indicates that it is possible to | ||
2785 | create new keywords by attempting to store those | ||
2786 | flags in the mailbox. | ||
2787 | |||
2788 | READ-ONLY The mailbox is selected read-only, or its access | ||
2789 | while selected has changed from read-write to | ||
2790 | read-only. | ||
2791 | |||
2792 | READ-WRITE The mailbox is selected read-write, or its access | ||
2793 | while selected has changed from read-only to | ||
2794 | read-write. | ||
2795 | |||
2796 | |||
2797 | |||
2798 | |||
2799 | |||
2800 | |||
2801 | |||
2802 | Crispin Standards Track [Page 50] | ||
2803 | |||
2804 | RFC 2060 IMAP4rev1 December 1996 | ||
2805 | |||
2806 | |||
2807 | TRYCREATE An APPEND or COPY attempt is failing because the | ||
2808 | target mailbox does not exist (as opposed to some | ||
2809 | other reason). This is a hint to the client that | ||
2810 | the operation can succeed if the mailbox is first | ||
2811 | created by the CREATE command. | ||
2812 | |||
2813 | UIDVALIDITY Followed by a decimal number, indicates the unique | ||
2814 | identifier validity value. | ||
2815 | |||
2816 | UNSEEN Followed by a decimal number, indicates the number | ||
2817 | of the first message without the \Seen flag set. | ||
2818 | |||
2819 | Additional response codes defined by particular client or server | ||
2820 | implementations SHOULD be prefixed with an "X" until they are | ||
2821 | added to a revision of this protocol. Client implementations | ||
2822 | SHOULD ignore response codes that they do not recognize. | ||
2823 | |||
2824 | 7.1.1. OK Response | ||
2825 | |||
2826 | Contents: OPTIONAL response code | ||
2827 | human-readable text | ||
2828 | |||
2829 | The OK response indicates an information message from the server. | ||
2830 | When tagged, it indicates successful completion of the associated | ||
2831 | command. The human-readable text MAY be presented to the user as | ||
2832 | an information message. The untagged form indicates an | ||
2833 | information-only message; the nature of the information MAY be | ||
2834 | indicated by a response code. | ||
2835 | |||
2836 | The untagged form is also used as one of three possible greetings | ||
2837 | at connection startup. It indicates that the connection is not | ||
2838 | yet authenticated and that a LOGIN command is needed. | ||
2839 | |||
2840 | Example: S: * OK IMAP4rev1 server ready | ||
2841 | C: A001 LOGIN fred blurdybloop | ||
2842 | S: * OK [ALERT] System shutdown in 10 minutes | ||
2843 | S: A001 OK LOGIN Completed | ||
2844 | |||
2845 | 7.1.2. NO Response | ||
2846 | |||
2847 | Contents: OPTIONAL response code | ||
2848 | human-readable text | ||
2849 | |||
2850 | The NO response indicates an operational error message from the | ||
2851 | server. When tagged, it indicates unsuccessful completion of the | ||
2852 | associated command. The untagged form indicates a warning; the | ||
2853 | command can still complete successfully. The human-readable text | ||
2854 | describes the condition. | ||
2855 | |||
2856 | |||
2857 | |||
2858 | Crispin Standards Track [Page 51] | ||
2859 | |||
2860 | RFC 2060 IMAP4rev1 December 1996 | ||
2861 | |||
2862 | |||
2863 | Example: C: A222 COPY 1:2 owatagusiam | ||
2864 | S: * NO Disk is 98% full, please delete unnecessary data | ||
2865 | S: A222 OK COPY completed | ||
2866 | C: A223 COPY 3:200 blurdybloop | ||
2867 | S: * NO Disk is 98% full, please delete unnecessary data | ||
2868 | S: * NO Disk is 99% full, please delete unnecessary data | ||
2869 | S: A223 NO COPY failed: disk is full | ||
2870 | |||
2871 | 7.1.3. BAD Response | ||
2872 | |||
2873 | Contents: OPTIONAL response code | ||
2874 | human-readable text | ||
2875 | |||
2876 | The BAD response indicates an error message from the server. When | ||
2877 | tagged, it reports a protocol-level error in the client's command; | ||
2878 | the tag indicates the command that caused the error. The untagged | ||
2879 | form indicates a protocol-level error for which the associated | ||
2880 | command can not be determined; it can also indicate an internal | ||
2881 | server failure. The human-readable text describes the condition. | ||
2882 | |||
2883 | Example: C: ...very long command line... | ||
2884 | S: * BAD Command line too long | ||
2885 | C: ...empty line... | ||
2886 | S: * BAD Empty command line | ||
2887 | C: A443 EXPUNGE | ||
2888 | S: * BAD Disk crash, attempting salvage to a new disk! | ||
2889 | S: * OK Salvage successful, no data lost | ||
2890 | S: A443 OK Expunge completed | ||
2891 | |||
2892 | 7.1.4. PREAUTH Response | ||
2893 | |||
2894 | Contents: OPTIONAL response code | ||
2895 | human-readable text | ||
2896 | |||
2897 | The PREAUTH response is always untagged, and is one of three | ||
2898 | possible greetings at connection startup. It indicates that the | ||
2899 | connection has already been authenticated by external means and | ||
2900 | thus no LOGIN command is needed. | ||
2901 | |||
2902 | Example: S: * PREAUTH IMAP4rev1 server logged in as Smith | ||
2903 | |||
2904 | 7.1.5. BYE Response | ||
2905 | |||
2906 | Contents: OPTIONAL response code | ||
2907 | human-readable text | ||
2908 | |||
2909 | |||
2910 | |||
2911 | |||
2912 | |||
2913 | |||
2914 | Crispin Standards Track [Page 52] | ||
2915 | |||
2916 | RFC 2060 IMAP4rev1 December 1996 | ||
2917 | |||
2918 | |||
2919 | The BYE response is always untagged, and indicates that the server | ||
2920 | is about to close the connection. The human-readable text MAY be | ||
2921 | displayed to the user in a status report by the client. The BYE | ||
2922 | response is sent under one of four conditions: | ||
2923 | |||
2924 | 1) as part of a normal logout sequence. The server will close | ||
2925 | the connection after sending the tagged OK response to the | ||
2926 | LOGOUT command. | ||
2927 | |||
2928 | 2) as a panic shutdown announcement. The server closes the | ||
2929 | connection immediately. | ||
2930 | |||
2931 | 3) as an announcement of an inactivity autologout. The server | ||
2932 | closes the connection immediately. | ||
2933 | |||
2934 | 4) as one of three possible greetings at connection startup, | ||
2935 | indicating that the server is not willing to accept a | ||
2936 | connection from this client. The server closes the | ||
2937 | connection immediately. | ||
2938 | |||
2939 | The difference between a BYE that occurs as part of a normal | ||
2940 | LOGOUT sequence (the first case) and a BYE that occurs because of | ||
2941 | a failure (the other three cases) is that the connection closes | ||
2942 | immediately in the failure case. | ||
2943 | |||
2944 | Example: S: * BYE Autologout; idle for too long | ||
2945 | |||
2946 | 7.2. Server Responses - Server and Mailbox Status | ||
2947 | |||
2948 | These responses are always untagged. This is how server and mailbox | ||
2949 | status data are transmitted from the server to the client. Many of | ||
2950 | these responses typically result from a command with the same name. | ||
2951 | |||
2952 | 7.2.1. CAPABILITY Response | ||
2953 | |||
2954 | Contents: capability listing | ||
2955 | |||
2956 | The CAPABILITY response occurs as a result of a CAPABILITY | ||
2957 | command. The capability listing contains a space-separated | ||
2958 | listing of capability names that the server supports. The | ||
2959 | capability listing MUST include the atom "IMAP4rev1". | ||
2960 | |||
2961 | A capability name which begins with "AUTH=" indicates that the | ||
2962 | server supports that particular authentication mechanism. | ||
2963 | |||
2964 | |||
2965 | |||
2966 | |||
2967 | |||
2968 | |||
2969 | |||
2970 | Crispin Standards Track [Page 53] | ||
2971 | |||
2972 | RFC 2060 IMAP4rev1 December 1996 | ||
2973 | |||
2974 | |||
2975 | Other capability names indicate that the server supports an | ||
2976 | extension, revision, or amendment to the IMAP4rev1 protocol. | ||
2977 | Server responses MUST conform to this document until the client | ||
2978 | issues a command that uses the associated capability. | ||
2979 | |||
2980 | Capability names MUST either begin with "X" or be standard or | ||
2981 | standards-track IMAP4rev1 extensions, revisions, or amendments | ||
2982 | registered with IANA. A server MUST NOT offer unregistered or | ||
2983 | non-standard capability names, unless such names are prefixed with | ||
2984 | an "X". | ||
2985 | |||
2986 | Client implementations SHOULD NOT require any capability name | ||
2987 | other than "IMAP4rev1", and MUST ignore any unknown capability | ||
2988 | names. | ||
2989 | |||
2990 | Example: S: * CAPABILITY IMAP4rev1 AUTH=KERBEROS_V4 XPIG-LATIN | ||
2991 | |||
2992 | 7.2.2. LIST Response | ||
2993 | |||
2994 | Contents: name attributes | ||
2995 | hierarchy delimiter | ||
2996 | name | ||
2997 | |||
2998 | The LIST response occurs as a result of a LIST command. It | ||
2999 | returns a single name that matches the LIST specification. There | ||
3000 | can be multiple LIST responses for a single LIST command. | ||
3001 | |||
3002 | Four name attributes are defined: | ||
3003 | |||
3004 | \Noinferiors It is not possible for any child levels of | ||
3005 | hierarchy to exist under this name; no child levels | ||
3006 | exist now and none can be created in the future. | ||
3007 | |||
3008 | \Noselect It is not possible to use this name as a selectable | ||
3009 | mailbox. | ||
3010 | |||
3011 | \Marked The mailbox has been marked "interesting" by the | ||
3012 | server; the mailbox probably contains messages that | ||
3013 | have been added since the last time the mailbox was | ||
3014 | selected. | ||
3015 | |||
3016 | \Unmarked The mailbox does not contain any additional | ||
3017 | messages since the last time the mailbox was | ||
3018 | selected. | ||
3019 | |||
3020 | If it is not feasible for the server to determine whether the | ||
3021 | mailbox is "interesting" or not, or if the name is a \Noselect | ||
3022 | name, the server SHOULD NOT send either \Marked or \Unmarked. | ||
3023 | |||
3024 | |||
3025 | |||
3026 | Crispin Standards Track [Page 54] | ||
3027 | |||
3028 | RFC 2060 IMAP4rev1 December 1996 | ||
3029 | |||
3030 | |||
3031 | The hierarchy delimiter is a character used to delimit levels of | ||
3032 | hierarchy in a mailbox name. A client can use it to create child | ||
3033 | mailboxes, and to search higher or lower levels of naming | ||
3034 | hierarchy. All children of a top-level hierarchy node MUST use | ||
3035 | the same separator character. A NIL hierarchy delimiter means | ||
3036 | that no hierarchy exists; the name is a "flat" name. | ||
3037 | |||
3038 | The name represents an unambiguous left-to-right hierarchy, and | ||
3039 | MUST be valid for use as a reference in LIST and LSUB commands. | ||
3040 | Unless \Noselect is indicated, the name MUST also be valid as an | ||
3041 | argument for commands, such as SELECT, that accept mailbox | ||
3042 | names. | ||
3043 | |||
3044 | Example: S: * LIST (\Noselect) "/" ~/Mail/foo | ||
3045 | |||
3046 | 7.2.3. LSUB Response | ||
3047 | |||
3048 | Contents: name attributes | ||
3049 | hierarchy delimiter | ||
3050 | name | ||
3051 | |||
3052 | The LSUB response occurs as a result of an LSUB command. It | ||
3053 | returns a single name that matches the LSUB specification. There | ||
3054 | can be multiple LSUB responses for a single LSUB command. The | ||
3055 | data is identical in format to the LIST response. | ||
3056 | |||
3057 | Example: S: * LSUB () "." #news.comp.mail.misc | ||
3058 | |||
3059 | 7.2.4 STATUS Response | ||
3060 | |||
3061 | Contents: name | ||
3062 | status parenthesized list | ||
3063 | |||
3064 | The STATUS response occurs as a result of an STATUS command. It | ||
3065 | returns the mailbox name that matches the STATUS specification and | ||
3066 | the requested mailbox status information. | ||
3067 | |||
3068 | Example: S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292) | ||
3069 | |||
3070 | 7.2.5. SEARCH Response | ||
3071 | |||
3072 | Contents: zero or more numbers | ||
3073 | |||
3074 | |||
3075 | |||
3076 | |||
3077 | |||
3078 | |||
3079 | |||
3080 | |||
3081 | |||
3082 | Crispin Standards Track [Page 55] | ||
3083 | |||
3084 | RFC 2060 IMAP4rev1 December 1996 | ||
3085 | |||
3086 | |||
3087 | The SEARCH response occurs as a result of a SEARCH or UID SEARCH | ||
3088 | command. The number(s) refer to those messages that match the | ||
3089 | search criteria. For SEARCH, these are message sequence numbers; | ||
3090 | for UID SEARCH, these are unique identifiers. Each number is | ||
3091 | delimited by a space. | ||
3092 | |||
3093 | Example: S: * SEARCH 2 3 6 | ||
3094 | |||
3095 | 7.2.6. FLAGS Response | ||
3096 | |||
3097 | Contents: flag parenthesized list | ||
3098 | |||
3099 | The FLAGS response occurs as a result of a SELECT or EXAMINE | ||
3100 | command. The flag parenthesized list identifies the flags (at a | ||
3101 | minimum, the system-defined flags) that are applicable for this | ||
3102 | mailbox. Flags other than the system flags can also exist, | ||
3103 | depending on server implementation. | ||
3104 | |||
3105 | The update from the FLAGS response MUST be recorded by the client. | ||
3106 | |||
3107 | Example: S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) | ||
3108 | |||
3109 | 7.3. Server Responses - Mailbox Size | ||
3110 | |||
3111 | These responses are always untagged. This is how changes in the size | ||
3112 | of the mailbox are trasnmitted from the server to the client. | ||
3113 | Immediately following the "*" token is a number that represents a | ||
3114 | message count. | ||
3115 | |||
3116 | 7.3.1. EXISTS Response | ||
3117 | |||
3118 | Contents: none | ||
3119 | |||
3120 | The EXISTS response reports the number of messages in the mailbox. | ||
3121 | This response occurs as a result of a SELECT or EXAMINE command, | ||
3122 | and if the size of the mailbox changes (e.g. new mail). | ||
3123 | |||
3124 | The update from the EXISTS response MUST be recorded by the | ||
3125 | client. | ||
3126 | |||
3127 | Example: S: * 23 EXISTS | ||
3128 | |||
3129 | |||
3130 | |||
3131 | |||
3132 | |||
3133 | |||
3134 | |||
3135 | |||
3136 | |||
3137 | |||
3138 | Crispin Standards Track [Page 56] | ||
3139 | |||
3140 | RFC 2060 IMAP4rev1 December 1996 | ||
3141 | |||
3142 | |||
3143 | 7.3.2. RECENT Response | ||
3144 | |||
3145 | Contents: none | ||
3146 | |||
3147 | The RECENT response reports the number of messages with the | ||
3148 | \Recent flag set. This response occurs as a result of a SELECT or | ||
3149 | EXAMINE command, and if the size of the mailbox changes (e.g. new | ||
3150 | mail). | ||
3151 | |||
3152 | Note: It is not guaranteed that the message sequence numbers of | ||
3153 | recent messages will be a contiguous range of the highest n | ||
3154 | messages in the mailbox (where n is the value reported by the | ||
3155 | RECENT response). Examples of situations in which this is not | ||
3156 | the case are: multiple clients having the same mailbox open | ||
3157 | (the first session to be notified will see it as recent, others | ||
3158 | will probably see it as non-recent), and when the mailbox is | ||
3159 | re-ordered by a non-IMAP agent. | ||
3160 | |||
3161 | The only reliable way to identify recent messages is to look at | ||
3162 | message flags to see which have the \Recent flag set, or to do | ||
3163 | a SEARCH RECENT. | ||
3164 | |||
3165 | The update from the RECENT response MUST be recorded by the | ||
3166 | client. | ||
3167 | |||
3168 | Example: S: * 5 RECENT | ||
3169 | |||
3170 | 7.4. Server Responses - Message Status | ||
3171 | |||
3172 | These responses are always untagged. This is how message data are | ||
3173 | transmitted from the server to the client, often as a result of a | ||
3174 | command with the same name. Immediately following the "*" token is a | ||
3175 | number that represents a message sequence number. | ||
3176 | |||
3177 | 7.4.1. EXPUNGE Response | ||
3178 | |||
3179 | Contents: none | ||
3180 | |||
3181 | The EXPUNGE response reports that the specified message sequence | ||
3182 | number has been permanently removed from the mailbox. The message | ||
3183 | sequence number for each successive message in the mailbox is | ||
3184 | immediately decremented by 1, and this decrement is reflected in | ||
3185 | message sequence numbers in subsequent responses (including other | ||
3186 | untagged EXPUNGE responses). | ||
3187 | |||
3188 | As a result of the immediate decrement rule, message sequence | ||
3189 | numbers that appear in a set of successive EXPUNGE responses | ||
3190 | depend upon whether the messages are removed starting from lower | ||
3191 | |||
3192 | |||
3193 | |||
3194 | Crispin Standards Track [Page 57] | ||
3195 | |||
3196 | RFC 2060 IMAP4rev1 December 1996 | ||
3197 | |||
3198 | |||
3199 | numbers to higher numbers, or from higher numbers to lower | ||
3200 | numbers. For example, if the last 5 messages in a 9-message | ||
3201 | mailbox are expunged; a "lower to higher" server will send five | ||
3202 | untagged EXPUNGE responses for message sequence number 5, whereas | ||
3203 | a "higher to lower server" will send successive untagged EXPUNGE | ||
3204 | responses for message sequence numbers 9, 8, 7, 6, and 5. | ||
3205 | |||
3206 | An EXPUNGE response MUST NOT be sent when no command is in | ||
3207 | progress; nor while responding to a FETCH, STORE, or SEARCH | ||
3208 | command. This rule is necessary to prevent a loss of | ||
3209 | synchronization of message sequence numbers between client and | ||
3210 | server. | ||
3211 | |||
3212 | The update from the EXPUNGE response MUST be recorded by the | ||
3213 | client. | ||
3214 | |||
3215 | Example: S: * 44 EXPUNGE | ||
3216 | |||
3217 | 7.4.2. FETCH Response | ||
3218 | |||
3219 | Contents: message data | ||
3220 | |||
3221 | The FETCH response returns data about a message to the client. | ||
3222 | The data are pairs of data item names and their values in | ||
3223 | parentheses. This response occurs as the result of a FETCH or | ||
3224 | STORE command, as well as by unilateral server decision (e.g. flag | ||
3225 | updates). | ||
3226 | |||
3227 | The current data items are: | ||
3228 | |||
3229 | BODY A form of BODYSTRUCTURE without extension data. | ||
3230 | |||
3231 | BODY[<section>]<<origin_octet>> | ||
3232 | A string expressing the body contents of the | ||
3233 | specified section. The string SHOULD be | ||
3234 | interpreted by the client according to the content | ||
3235 | transfer encoding, body type, and subtype. | ||
3236 | |||
3237 | If the origin octet is specified, this string is a | ||
3238 | substring of the entire body contents, starting at | ||
3239 | that origin octet. This means that BODY[]<0> MAY | ||
3240 | be truncated, but BODY[] is NEVER truncated. | ||
3241 | |||
3242 | 8-bit textual data is permitted if a [CHARSET] | ||
3243 | identifier is part of the body parameter | ||
3244 | parenthesized list for this section. Note that | ||
3245 | headers (part specifiers HEADER or MIME, or the | ||
3246 | header portion of a MESSAGE/RFC822 part), MUST be | ||
3247 | |||
3248 | |||
3249 | |||
3250 | Crispin Standards Track [Page 58] | ||
3251 | |||
3252 | RFC 2060 IMAP4rev1 December 1996 | ||
3253 | |||
3254 | |||
3255 | 7-bit; 8-bit characters are not permitted in | ||
3256 | headers. Note also that the blank line at the end | ||
3257 | of the header is always included in header data. | ||
3258 | |||
3259 | Non-textual data such as binary data MUST be | ||
3260 | transfer encoded into a textual form such as BASE64 | ||
3261 | prior to being sent to the client. To derive the | ||
3262 | original binary data, the client MUST decode the | ||
3263 | transfer encoded string. | ||
3264 | |||
3265 | BODYSTRUCTURE A parenthesized list that describes the [MIME-IMB] | ||
3266 | body structure of a message. This is computed by | ||
3267 | the server by parsing the [MIME-IMB] header fields, | ||
3268 | defaulting various fields as necessary. | ||
3269 | |||
3270 | For example, a simple text message of 48 lines and | ||
3271 | 2279 octets can have a body structure of: ("TEXT" | ||
3272 | "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 2279 | ||
3273 | 48) | ||
3274 | |||
3275 | Multiple parts are indicated by parenthesis | ||
3276 | nesting. Instead of a body type as the first | ||
3277 | element of the parenthesized list there is a nested | ||
3278 | body. The second element of the parenthesized list | ||
3279 | is the multipart subtype (mixed, digest, parallel, | ||
3280 | alternative, etc.). | ||
3281 | |||
3282 | For example, a two part message consisting of a | ||
3283 | text and a BASE645-encoded text attachment can have | ||
3284 | a body structure of: (("TEXT" "PLAIN" ("CHARSET" | ||
3285 | "US-ASCII") NIL NIL "7BIT" 1152 23)("TEXT" "PLAIN" | ||
3286 | ("CHARSET" "US-ASCII" "NAME" "cc.diff") | ||
3287 | "<960723163407.20117h@cac.washington.edu>" | ||
3288 | "Compiler diff" "BASE64" 4554 73) "MIXED")) | ||
3289 | |||
3290 | Extension data follows the multipart subtype. | ||
3291 | Extension data is never returned with the BODY | ||
3292 | fetch, but can be returned with a BODYSTRUCTURE | ||
3293 | fetch. Extension data, if present, MUST be in the | ||
3294 | defined order. | ||
3295 | |||
3296 | The extension data of a multipart body part are in | ||
3297 | the following order: | ||
3298 | |||
3299 | body parameter parenthesized list | ||
3300 | A parenthesized list of attribute/value pairs | ||
3301 | [e.g. ("foo" "bar" "baz" "rag") where "bar" is | ||
3302 | the value of "foo" and "rag" is the value of | ||
3303 | |||
3304 | |||
3305 | |||
3306 | Crispin Standards Track [Page 59] | ||
3307 | |||
3308 | RFC 2060 IMAP4rev1 December 1996 | ||
3309 | |||
3310 | |||
3311 | "baz"] as defined in [MIME-IMB]. | ||
3312 | |||
3313 | body disposition | ||
3314 | A parenthesized list, consisting of a | ||
3315 | disposition type string followed by a | ||
3316 | parenthesized list of disposition | ||
3317 | attribute/value pairs. The disposition type and | ||
3318 | attribute names will be defined in a future | ||
3319 | standards-track revision to [DISPOSITION]. | ||
3320 | |||
3321 | body language | ||
3322 | A string or parenthesized list giving the body | ||
3323 | language value as defined in [LANGUAGE-TAGS]. | ||
3324 | |||
3325 | Any following extension data are not yet defined in | ||
3326 | this version of the protocol. Such extension data | ||
3327 | can consist of zero or more NILs, strings, numbers, | ||
3328 | or potentially nested parenthesized lists of such | ||
3329 | data. Client implementations that do a | ||
3330 | BODYSTRUCTURE fetch MUST be prepared to accept such | ||
3331 | extension data. Server implementations MUST NOT | ||
3332 | send such extension data until it has been defined | ||
3333 | by a revision of this protocol. | ||
3334 | |||
3335 | The basic fields of a non-multipart body part are | ||
3336 | in the following order: | ||
3337 | |||
3338 | body type | ||
3339 | A string giving the content media type name as | ||
3340 | defined in [MIME-IMB]. | ||
3341 | |||
3342 | body subtype | ||
3343 | A string giving the content subtype name as | ||
3344 | defined in [MIME-IMB]. | ||
3345 | |||
3346 | body parameter parenthesized list | ||
3347 | A parenthesized list of attribute/value pairs | ||
3348 | [e.g. ("foo" "bar" "baz" "rag") where "bar" is | ||
3349 | the value of "foo" and "rag" is the value of | ||
3350 | "baz"] as defined in [MIME-IMB]. | ||
3351 | |||
3352 | body id | ||
3353 | A string giving the content id as defined in | ||
3354 | [MIME-IMB]. | ||
3355 | |||
3356 | body description | ||
3357 | A string giving the content description as | ||
3358 | defined in [MIME-IMB]. | ||
3359 | |||
3360 | |||
3361 | |||
3362 | Crispin Standards Track [Page 60] | ||
3363 | |||
3364 | RFC 2060 IMAP4rev1 December 1996 | ||
3365 | |||
3366 | |||
3367 | body encoding | ||
3368 | A string giving the content transfer encoding as | ||
3369 | defined in [MIME-IMB]. | ||
3370 | |||
3371 | body size | ||
3372 | A number giving the size of the body in octets. | ||
3373 | Note that this size is the size in its transfer | ||
3374 | encoding and not the resulting size after any | ||
3375 | decoding. | ||
3376 | |||
3377 | A body type of type MESSAGE and subtype RFC822 | ||
3378 | contains, immediately after the basic fields, the | ||
3379 | envelope structure, body structure, and size in | ||
3380 | text lines of the encapsulated message. | ||
3381 | |||
3382 | A body type of type TEXT contains, immediately | ||
3383 | after the basic fields, the size of the body in | ||
3384 | text lines. Note that this size is the size in its | ||
3385 | content transfer encoding and not the resulting | ||
3386 | size after any decoding. | ||
3387 | |||
3388 | Extension data follows the basic fields and the | ||
3389 | type-specific fields listed above. Extension data | ||
3390 | is never returned with the BODY fetch, but can be | ||
3391 | returned with a BODYSTRUCTURE fetch. Extension | ||
3392 | data, if present, MUST be in the defined order. | ||
3393 | |||
3394 | The extension data of a non-multipart body part are | ||
3395 | in the following order: | ||
3396 | |||
3397 | body MD5 | ||
3398 | A string giving the body MD5 value as defined in | ||
3399 | [MD5]. | ||
3400 | |||
3401 | body disposition | ||
3402 | A parenthesized list with the same content and | ||
3403 | function as the body disposition for a multipart | ||
3404 | body part. | ||
3405 | |||
3406 | body language | ||
3407 | A string or parenthesized list giving the body | ||
3408 | language value as defined in [LANGUAGE-TAGS]. | ||
3409 | |||
3410 | Any following extension data are not yet defined in | ||
3411 | this version of the protocol, and would be as | ||
3412 | described above under multipart extension data. | ||
3413 | |||
3414 | |||
3415 | |||
3416 | |||
3417 | |||
3418 | Crispin Standards Track [Page 61] | ||
3419 | |||
3420 | RFC 2060 IMAP4rev1 December 1996 | ||
3421 | |||
3422 | |||
3423 | ENVELOPE A parenthesized list that describes the envelope | ||
3424 | structure of a message. This is computed by the | ||
3425 | server by parsing the [RFC-822] header into the | ||
3426 | component parts, defaulting various fields as | ||
3427 | necessary. | ||
3428 | |||
3429 | The fields of the envelope structure are in the | ||
3430 | following order: date, subject, from, sender, | ||
3431 | reply-to, to, cc, bcc, in-reply-to, and message-id. | ||
3432 | The date, subject, in-reply-to, and message-id | ||
3433 | fields are strings. The from, sender, reply-to, | ||
3434 | to, cc, and bcc fields are parenthesized lists of | ||
3435 | address structures. | ||
3436 | |||
3437 | An address structure is a parenthesized list that | ||
3438 | describes an electronic mail address. The fields | ||
3439 | of an address structure are in the following order: | ||
3440 | personal name, [SMTP] at-domain-list (source | ||
3441 | route), mailbox name, and host name. | ||
3442 | |||
3443 | [RFC-822] group syntax is indicated by a special | ||
3444 | form of address structure in which the host name | ||
3445 | field is NIL. If the mailbox name field is also | ||
3446 | NIL, this is an end of group marker (semi-colon in | ||
3447 | RFC 822 syntax). If the mailbox name field is | ||
3448 | non-NIL, this is a start of group marker, and the | ||
3449 | mailbox name field holds the group name phrase. | ||
3450 | |||
3451 | Any field of an envelope or address structure that | ||
3452 | is not applicable is presented as NIL. Note that | ||
3453 | the server MUST default the reply-to and sender | ||
3454 | fields from the from field; a client is not | ||
3455 | expected to know to do this. | ||
3456 | |||
3457 | FLAGS A parenthesized list of flags that are set for this | ||
3458 | message. | ||
3459 | |||
3460 | INTERNALDATE A string representing the internal date of the | ||
3461 | message. | ||
3462 | |||
3463 | RFC822 Equivalent to BODY[]. | ||
3464 | |||
3465 | RFC822.HEADER Equivalent to BODY.PEEK[HEADER]. | ||
3466 | |||
3467 | RFC822.SIZE A number expressing the [RFC-822] size of the | ||
3468 | message. | ||
3469 | |||
3470 | RFC822.TEXT Equivalent to BODY[TEXT]. | ||
3471 | |||
3472 | |||
3473 | |||
3474 | Crispin Standards Track [Page 62] | ||
3475 | |||
3476 | RFC 2060 IMAP4rev1 December 1996 | ||
3477 | |||
3478 | |||
3479 | UID A number expressing the unique identifier of the | ||
3480 | message. | ||
3481 | |||
3482 | |||
3483 | Example: S: * 23 FETCH (FLAGS (\Seen) RFC822.SIZE 44827) | ||
3484 | |||
3485 | 7.5. Server Responses - Command Continuation Request | ||
3486 | |||
3487 | The command continuation request response is indicated by a "+" token | ||
3488 | instead of a tag. This form of response indicates that the server is | ||
3489 | ready to accept the continuation of a command from the client. The | ||
3490 | remainder of this response is a line of text. | ||
3491 | |||
3492 | This response is used in the AUTHORIZATION command to transmit server | ||
3493 | data to the client, and request additional client data. This | ||
3494 | response is also used if an argument to any command is a literal. | ||
3495 | |||
3496 | The client is not permitted to send the octets of the literal unless | ||
3497 | the server indicates that it expects it. This permits the server to | ||
3498 | process commands and reject errors on a line-by-line basis. The | ||
3499 | remainder of the command, including the CRLF that terminates a | ||
3500 | command, follows the octets of the literal. If there are any | ||
3501 | additional command arguments the literal octets are followed by a | ||
3502 | space and those arguments. | ||
3503 | |||
3504 | Example: C: A001 LOGIN {11} | ||
3505 | S: + Ready for additional command text | ||
3506 | C: FRED FOOBAR {7} | ||
3507 | S: + Ready for additional command text | ||
3508 | C: fat man | ||
3509 | S: A001 OK LOGIN completed | ||
3510 | C: A044 BLURDYBLOOP {102856} | ||
3511 | S: A044 BAD No such command as "BLURDYBLOOP" | ||
3512 | |||
3513 | 8. Sample IMAP4rev1 connection | ||
3514 | |||
3515 | The following is a transcript of an IMAP4rev1 connection. A long | ||
3516 | line in this sample is broken for editorial clarity. | ||
3517 | |||
3518 | S: * OK IMAP4rev1 Service Ready | ||
3519 | C: a001 login mrc secret | ||
3520 | S: a001 OK LOGIN completed | ||
3521 | C: a002 select inbox | ||
3522 | S: * 18 EXISTS | ||
3523 | S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) | ||
3524 | S: * 2 RECENT | ||
3525 | S: * OK [UNSEEN 17] Message 17 is the first unseen message | ||
3526 | S: * OK [UIDVALIDITY 3857529045] UIDs valid | ||
3527 | |||
3528 | |||
3529 | |||
3530 | Crispin Standards Track [Page 63] | ||
3531 | |||
3532 | RFC 2060 IMAP4rev1 December 1996 | ||
3533 | |||
3534 | |||
3535 | S: a002 OK [READ-WRITE] SELECT completed | ||
3536 | C: a003 fetch 12 full | ||
3537 | S: * 12 FETCH (FLAGS (\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700" | ||
3538 | RFC822.SIZE 4286 ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)" | ||
3539 | "IMAP4rev1 WG mtg summary and minutes" | ||
3540 | (("Terry Gray" NIL "gray" "cac.washington.edu")) | ||
3541 | (("Terry Gray" NIL "gray" "cac.washington.edu")) | ||
3542 | (("Terry Gray" NIL "gray" "cac.washington.edu")) | ||
3543 | ((NIL NIL "imap" "cac.washington.edu")) | ||
3544 | ((NIL NIL "minutes" "CNRI.Reston.VA.US") | ||
3545 | ("John Klensin" NIL "KLENSIN" "INFOODS.MIT.EDU")) NIL NIL | ||
3546 | "<B27397-0100000@cac.washington.edu>") | ||
3547 | BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028 92)) | ||
3548 | S: a003 OK FETCH completed | ||
3549 | C: a004 fetch 12 body[header] | ||
3550 | S: * 12 FETCH (BODY[HEADER] {350} | ||
3551 | S: Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT) | ||
3552 | S: From: Terry Gray <gray@cac.washington.edu> | ||
3553 | S: Subject: IMAP4rev1 WG mtg summary and minutes | ||
3554 | S: To: imap@cac.washington.edu | ||
3555 | S: cc: minutes@CNRI.Reston.VA.US, John Klensin <KLENSIN@INFOODS.MIT.EDU> | ||
3556 | S: Message-Id: <B27397-0100000@cac.washington.edu> | ||
3557 | S: MIME-Version: 1.0 | ||
3558 | S: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | ||
3559 | S: | ||
3560 | S: ) | ||
3561 | S: a004 OK FETCH completed | ||
3562 | C: a005 store 12 +flags \deleted | ||
3563 | S: * 12 FETCH (FLAGS (\Seen \Deleted)) | ||
3564 | S: a005 OK +FLAGS completed | ||
3565 | C: a006 logout | ||
3566 | S: * BYE IMAP4rev1 server terminating connection | ||
3567 | S: a006 OK LOGOUT completed | ||
3568 | |||
3569 | 9. Formal Syntax | ||
3570 | |||
3571 | The following syntax specification uses the augmented Backus-Naur | ||
3572 | Form (BNF) notation as specified in [RFC-822] with one exception; the | ||
3573 | delimiter used with the "#" construct is a single space (SPACE) and | ||
3574 | not one or more commas. | ||
3575 | |||
3576 | In the case of alternative or optional rules in which a later rule | ||
3577 | overlaps an earlier rule, the rule which is listed earlier MUST take | ||
3578 | priority. For example, "\Seen" when parsed as a flag is the \Seen | ||
3579 | flag name and not a flag_extension, even though "\Seen" could be | ||
3580 | parsed as a flag_extension. Some, but not all, instances of this | ||
3581 | rule are noted below. | ||
3582 | |||
3583 | |||
3584 | |||
3585 | |||
3586 | Crispin Standards Track [Page 64] | ||
3587 | |||
3588 | RFC 2060 IMAP4rev1 December 1996 | ||
3589 | |||
3590 | |||
3591 | Except as noted otherwise, all alphabetic characters are case- | ||
3592 | insensitive. The use of upper or lower case characters to define | ||
3593 | token strings is for editorial clarity only. Implementations MUST | ||
3594 | accept these strings in a case-insensitive fashion. | ||
3595 | |||
3596 | address ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox | ||
3597 | SPACE addr_host ")" | ||
3598 | |||
3599 | addr_adl ::= nstring | ||
3600 | ;; Holds route from [RFC-822] route-addr if | ||
3601 | ;; non-NIL | ||
3602 | |||
3603 | addr_host ::= nstring | ||
3604 | ;; NIL indicates [RFC-822] group syntax. | ||
3605 | ;; Otherwise, holds [RFC-822] domain name | ||
3606 | |||
3607 | addr_mailbox ::= nstring | ||
3608 | ;; NIL indicates end of [RFC-822] group; if | ||
3609 | ;; non-NIL and addr_host is NIL, holds | ||
3610 | ;; [RFC-822] group name. | ||
3611 | ;; Otherwise, holds [RFC-822] local-part | ||
3612 | |||
3613 | addr_name ::= nstring | ||
3614 | ;; Holds phrase from [RFC-822] mailbox if | ||
3615 | ;; non-NIL | ||
3616 | |||
3617 | alpha ::= "A" / "B" / "C" / "D" / "E" / "F" / "G" / "H" / | ||
3618 | "I" / "J" / "K" / "L" / "M" / "N" / "O" / "P" / | ||
3619 | "Q" / "R" / "S" / "T" / "U" / "V" / "W" / "X" / | ||
3620 | "Y" / "Z" / | ||
3621 | "a" / "b" / "c" / "d" / "e" / "f" / "g" / "h" / | ||
3622 | "i" / "j" / "k" / "l" / "m" / "n" / "o" / "p" / | ||
3623 | "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" / | ||
3624 | "y" / "z" | ||
3625 | ;; Case-sensitive | ||
3626 | |||
3627 | append ::= "APPEND" SPACE mailbox [SPACE flag_list] | ||
3628 | [SPACE date_time] SPACE literal | ||
3629 | |||
3630 | astring ::= atom / string | ||
3631 | |||
3632 | atom ::= 1*ATOM_CHAR | ||
3633 | |||
3634 | ATOM_CHAR ::= <any CHAR except atom_specials> | ||
3635 | |||
3636 | atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / | ||
3637 | quoted_specials | ||
3638 | |||
3639 | |||
3640 | |||
3641 | |||
3642 | Crispin Standards Track [Page 65] | ||
3643 | |||
3644 | RFC 2060 IMAP4rev1 December 1996 | ||
3645 | |||
3646 | |||
3647 | authenticate ::= "AUTHENTICATE" SPACE auth_type *(CRLF base64) | ||
3648 | |||
3649 | auth_type ::= atom | ||
3650 | ;; Defined by [IMAP-AUTH] | ||
3651 | |||
3652 | base64 ::= *(4base64_char) [base64_terminal] | ||
3653 | |||
3654 | base64_char ::= alpha / digit / "+" / "/" | ||
3655 | |||
3656 | base64_terminal ::= (2base64_char "==") / (3base64_char "=") | ||
3657 | |||
3658 | body ::= "(" body_type_1part / body_type_mpart ")" | ||
3659 | |||
3660 | body_extension ::= nstring / number / "(" 1#body_extension ")" | ||
3661 | ;; Future expansion. Client implementations | ||
3662 | ;; MUST accept body_extension fields. Server | ||
3663 | ;; implementations MUST NOT generate | ||
3664 | ;; body_extension fields except as defined by | ||
3665 | ;; future standard or standards-track | ||
3666 | ;; revisions of this specification. | ||
3667 | |||
3668 | body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp | ||
3669 | [SPACE body_fld_lang | ||
3670 | [SPACE 1#body_extension]]] | ||
3671 | ;; MUST NOT be returned on non-extensible | ||
3672 | ;; "BODY" fetch | ||
3673 | |||
3674 | body_ext_mpart ::= body_fld_param | ||
3675 | [SPACE body_fld_dsp SPACE body_fld_lang | ||
3676 | [SPACE 1#body_extension]] | ||
3677 | ;; MUST NOT be returned on non-extensible | ||
3678 | ;; "BODY" fetch | ||
3679 | |||
3680 | body_fields ::= body_fld_param SPACE body_fld_id SPACE | ||
3681 | body_fld_desc SPACE body_fld_enc SPACE | ||
3682 | body_fld_octets | ||
3683 | |||
3684 | body_fld_desc ::= nstring | ||
3685 | |||
3686 | body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil | ||
3687 | |||
3688 | body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ | ||
3689 | "QUOTED-PRINTABLE") <">) / string | ||
3690 | |||
3691 | body_fld_id ::= nstring | ||
3692 | |||
3693 | body_fld_lang ::= nstring / "(" 1#string ")" | ||
3694 | |||
3695 | |||
3696 | |||
3697 | |||
3698 | Crispin Standards Track [Page 66] | ||
3699 | |||
3700 | RFC 2060 IMAP4rev1 December 1996 | ||
3701 | |||
3702 | |||
3703 | body_fld_lines ::= number | ||
3704 | |||
3705 | body_fld_md5 ::= nstring | ||
3706 | |||
3707 | body_fld_octets ::= number | ||
3708 | |||
3709 | body_fld_param ::= "(" 1#(string SPACE string) ")" / nil | ||
3710 | |||
3711 | body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) | ||
3712 | [SPACE body_ext_1part] | ||
3713 | |||
3714 | body_type_basic ::= media_basic SPACE body_fields | ||
3715 | ;; MESSAGE subtype MUST NOT be "RFC822" | ||
3716 | |||
3717 | body_type_mpart ::= 1*body SPACE media_subtype | ||
3718 | [SPACE body_ext_mpart] | ||
3719 | |||
3720 | body_type_msg ::= media_message SPACE body_fields SPACE envelope | ||
3721 | SPACE body SPACE body_fld_lines | ||
3722 | |||
3723 | body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines | ||
3724 | |||
3725 | capability ::= "AUTH=" auth_type / atom | ||
3726 | ;; New capabilities MUST begin with "X" or be | ||
3727 | ;; registered with IANA as standard or | ||
3728 | ;; standards-track | ||
3729 | |||
3730 | capability_data ::= "CAPABILITY" SPACE [1#capability SPACE] "IMAP4rev1" | ||
3731 | [SPACE 1#capability] | ||
3732 | ;; IMAP4rev1 servers which offer RFC 1730 | ||
3733 | ;; compatibility MUST list "IMAP4" as the first | ||
3734 | ;; capability. | ||
3735 | |||
3736 | CHAR ::= <any 7-bit US-ASCII character except NUL, | ||
3737 | 0x01 - 0x7f> | ||
3738 | |||
3739 | CHAR8 ::= <any 8-bit octet except NUL, 0x01 - 0xff> | ||
3740 | |||
3741 | command ::= tag SPACE (command_any / command_auth / | ||
3742 | command_nonauth / command_select) CRLF | ||
3743 | ;; Modal based on state | ||
3744 | |||
3745 | command_any ::= "CAPABILITY" / "LOGOUT" / "NOOP" / x_command | ||
3746 | ;; Valid in all states | ||
3747 | |||
3748 | command_auth ::= append / create / delete / examine / list / lsub / | ||
3749 | rename / select / status / subscribe / unsubscribe | ||
3750 | ;; Valid only in Authenticated or Selected state | ||
3751 | |||
3752 | |||
3753 | |||
3754 | Crispin Standards Track [Page 67] | ||
3755 | |||
3756 | RFC 2060 IMAP4rev1 December 1996 | ||
3757 | |||
3758 | |||
3759 | command_nonauth ::= login / authenticate | ||
3760 | ;; Valid only when in Non-Authenticated state | ||
3761 | |||
3762 | command_select ::= "CHECK" / "CLOSE" / "EXPUNGE" / | ||
3763 | copy / fetch / store / uid / search | ||
3764 | ;; Valid only when in Selected state | ||
3765 | |||
3766 | continue_req ::= "+" SPACE (resp_text / base64) | ||
3767 | |||
3768 | copy ::= "COPY" SPACE set SPACE mailbox | ||
3769 | |||
3770 | CR ::= <ASCII CR, carriage return, 0x0D> | ||
3771 | |||
3772 | create ::= "CREATE" SPACE mailbox | ||
3773 | ;; Use of INBOX gives a NO error | ||
3774 | |||
3775 | CRLF ::= CR LF | ||
3776 | |||
3777 | CTL ::= <any ASCII control character and DEL, | ||
3778 | 0x00 - 0x1f, 0x7f> | ||
3779 | |||
3780 | date ::= date_text / <"> date_text <"> | ||
3781 | |||
3782 | date_day ::= 1*2digit | ||
3783 | ;; Day of month | ||
3784 | |||
3785 | date_day_fixed ::= (SPACE digit) / 2digit | ||
3786 | ;; Fixed-format version of date_day | ||
3787 | |||
3788 | date_month ::= "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / | ||
3789 | "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" | ||
3790 | |||
3791 | date_text ::= date_day "-" date_month "-" date_year | ||
3792 | |||
3793 | date_year ::= 4digit | ||
3794 | |||
3795 | date_time ::= <"> date_day_fixed "-" date_month "-" date_year | ||
3796 | SPACE time SPACE zone <"> | ||
3797 | |||
3798 | delete ::= "DELETE" SPACE mailbox | ||
3799 | ;; Use of INBOX gives a NO error | ||
3800 | |||
3801 | digit ::= "0" / digit_nz | ||
3802 | |||
3803 | digit_nz ::= "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / | ||
3804 | "9" | ||
3805 | |||
3806 | |||
3807 | |||
3808 | |||
3809 | |||
3810 | Crispin Standards Track [Page 68] | ||
3811 | |||
3812 | RFC 2060 IMAP4rev1 December 1996 | ||
3813 | |||
3814 | |||
3815 | envelope ::= "(" env_date SPACE env_subject SPACE env_from | ||
3816 | SPACE env_sender SPACE env_reply_to SPACE env_to | ||
3817 | SPACE env_cc SPACE env_bcc SPACE env_in_reply_to | ||
3818 | SPACE env_message_id ")" | ||
3819 | |||
3820 | env_bcc ::= "(" 1*address ")" / nil | ||
3821 | |||
3822 | env_cc ::= "(" 1*address ")" / nil | ||
3823 | |||
3824 | env_date ::= nstring | ||
3825 | |||
3826 | env_from ::= "(" 1*address ")" / nil | ||
3827 | |||
3828 | env_in_reply_to ::= nstring | ||
3829 | |||
3830 | env_message_id ::= nstring | ||
3831 | |||
3832 | env_reply_to ::= "(" 1*address ")" / nil | ||
3833 | |||
3834 | env_sender ::= "(" 1*address ")" / nil | ||
3835 | |||
3836 | env_subject ::= nstring | ||
3837 | |||
3838 | env_to ::= "(" 1*address ")" / nil | ||
3839 | |||
3840 | examine ::= "EXAMINE" SPACE mailbox | ||
3841 | |||
3842 | fetch ::= "FETCH" SPACE set SPACE ("ALL" / "FULL" / | ||
3843 | "FAST" / fetch_att / "(" 1#fetch_att ")") | ||
3844 | |||
3845 | fetch_att ::= "ENVELOPE" / "FLAGS" / "INTERNALDATE" / | ||
3846 | "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / | ||
3847 | "BODY" ["STRUCTURE"] / "UID" / | ||
3848 | "BODY" [".PEEK"] section | ||
3849 | ["<" number "." nz_number ">"] | ||
3850 | |||
3851 | flag ::= "\Answered" / "\Flagged" / "\Deleted" / | ||
3852 | "\Seen" / "\Draft" / flag_keyword / flag_extension | ||
3853 | |||
3854 | flag_extension ::= "\" atom | ||
3855 | ;; Future expansion. Client implementations | ||
3856 | ;; MUST accept flag_extension flags. Server | ||
3857 | ;; implementations MUST NOT generate | ||
3858 | ;; flag_extension flags except as defined by | ||
3859 | ;; future standard or standards-track | ||
3860 | ;; revisions of this specification. | ||
3861 | |||
3862 | flag_keyword ::= atom | ||
3863 | |||
3864 | |||
3865 | |||
3866 | Crispin Standards Track [Page 69] | ||
3867 | |||
3868 | RFC 2060 IMAP4rev1 December 1996 | ||
3869 | |||
3870 | |||
3871 | flag_list ::= "(" #flag ")" | ||
3872 | |||
3873 | greeting ::= "*" SPACE (resp_cond_auth / resp_cond_bye) CRLF | ||
3874 | |||
3875 | header_fld_name ::= astring | ||
3876 | |||
3877 | header_list ::= "(" 1#header_fld_name ")" | ||
3878 | |||
3879 | LF ::= <ASCII LF, line feed, 0x0A> | ||
3880 | |||
3881 | list ::= "LIST" SPACE mailbox SPACE list_mailbox | ||
3882 | |||
3883 | list_mailbox ::= 1*(ATOM_CHAR / list_wildcards) / string | ||
3884 | |||
3885 | list_wildcards ::= "%" / "*" | ||
3886 | |||
3887 | literal ::= "{" number "}" CRLF *CHAR8 | ||
3888 | ;; Number represents the number of CHAR8 octets | ||
3889 | |||
3890 | login ::= "LOGIN" SPACE userid SPACE password | ||
3891 | |||
3892 | lsub ::= "LSUB" SPACE mailbox SPACE list_mailbox | ||
3893 | |||
3894 | mailbox ::= "INBOX" / astring | ||
3895 | ;; INBOX is case-insensitive. All case variants of | ||
3896 | ;; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX | ||
3897 | ;; not as an astring. Refer to section 5.1 for | ||
3898 | ;; further semantic details of mailbox names. | ||
3899 | |||
3900 | mailbox_data ::= "FLAGS" SPACE flag_list / | ||
3901 | "LIST" SPACE mailbox_list / | ||
3902 | "LSUB" SPACE mailbox_list / | ||
3903 | "MAILBOX" SPACE text / | ||
3904 | "SEARCH" [SPACE 1#nz_number] / | ||
3905 | "STATUS" SPACE mailbox SPACE | ||
3906 | "(" #<status_att number ")" / | ||
3907 | number SPACE "EXISTS" / number SPACE "RECENT" | ||
3908 | |||
3909 | mailbox_list ::= "(" #("\Marked" / "\Noinferiors" / | ||
3910 | "\Noselect" / "\Unmarked" / flag_extension) ")" | ||
3911 | SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox | ||
3912 | |||
3913 | media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" / | ||
3914 | "MESSAGE" / "VIDEO") <">) / string) | ||
3915 | SPACE media_subtype | ||
3916 | ;; Defined in [MIME-IMT] | ||
3917 | |||
3918 | media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <"> | ||
3919 | |||
3920 | |||
3921 | |||
3922 | Crispin Standards Track [Page 70] | ||
3923 | |||
3924 | RFC 2060 IMAP4rev1 December 1996 | ||
3925 | |||
3926 | |||
3927 | ;; Defined in [MIME-IMT] | ||
3928 | |||
3929 | media_subtype ::= string | ||
3930 | ;; Defined in [MIME-IMT] | ||
3931 | |||
3932 | media_text ::= <"> "TEXT" <"> SPACE media_subtype | ||
3933 | ;; Defined in [MIME-IMT] | ||
3934 | |||
3935 | message_data ::= nz_number SPACE ("EXPUNGE" / | ||
3936 | ("FETCH" SPACE msg_att)) | ||
3937 | |||
3938 | msg_att ::= "(" 1#("ENVELOPE" SPACE envelope / | ||
3939 | "FLAGS" SPACE "(" #(flag / "\Recent") ")" / | ||
3940 | "INTERNALDATE" SPACE date_time / | ||
3941 | "RFC822" [".HEADER" / ".TEXT"] SPACE nstring / | ||
3942 | "RFC822.SIZE" SPACE number / | ||
3943 | "BODY" ["STRUCTURE"] SPACE body / | ||
3944 | "BODY" section ["<" number ">"] SPACE nstring / | ||
3945 | "UID" SPACE uniqueid) ")" | ||
3946 | |||
3947 | nil ::= "NIL" | ||
3948 | |||
3949 | nstring ::= string / nil | ||
3950 | |||
3951 | number ::= 1*digit | ||
3952 | ;; Unsigned 32-bit integer | ||
3953 | ;; (0 <= n < 4,294,967,296) | ||
3954 | |||
3955 | nz_number ::= digit_nz *digit | ||
3956 | ;; Non-zero unsigned 32-bit integer | ||
3957 | ;; (0 < n < 4,294,967,296) | ||
3958 | |||
3959 | password ::= astring | ||
3960 | |||
3961 | quoted ::= <"> *QUOTED_CHAR <"> | ||
3962 | |||
3963 | QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / | ||
3964 | "\" quoted_specials | ||
3965 | |||
3966 | quoted_specials ::= <"> / "\" | ||
3967 | |||
3968 | rename ::= "RENAME" SPACE mailbox SPACE mailbox | ||
3969 | ;; Use of INBOX as a destination gives a NO error | ||
3970 | |||
3971 | response ::= *(continue_req / response_data) response_done | ||
3972 | |||
3973 | response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye / | ||
3974 | mailbox_data / message_data / capability_data) | ||
3975 | |||
3976 | |||
3977 | |||
3978 | Crispin Standards Track [Page 71] | ||
3979 | |||
3980 | RFC 2060 IMAP4rev1 December 1996 | ||
3981 | |||
3982 | |||
3983 | CRLF | ||
3984 | |||
3985 | response_done ::= response_tagged / response_fatal | ||
3986 | |||
3987 | response_fatal ::= "*" SPACE resp_cond_bye CRLF | ||
3988 | ;; Server closes connection immediately | ||
3989 | |||
3990 | response_tagged ::= tag SPACE resp_cond_state CRLF | ||
3991 | |||
3992 | resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text | ||
3993 | ;; Authentication condition | ||
3994 | |||
3995 | resp_cond_bye ::= "BYE" SPACE resp_text | ||
3996 | |||
3997 | resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text | ||
3998 | ;; Status condition | ||
3999 | |||
4000 | resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text) | ||
4001 | ;; text SHOULD NOT begin with "[" or "=" | ||
4002 | |||
4003 | resp_text_code ::= "ALERT" / "PARSE" / | ||
4004 | "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" / | ||
4005 | "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / | ||
4006 | "UIDVALIDITY" SPACE nz_number / | ||
4007 | "UNSEEN" SPACE nz_number / | ||
4008 | atom [SPACE 1*<any TEXT_CHAR except "]">] | ||
4009 | |||
4010 | search ::= "SEARCH" SPACE ["CHARSET" SPACE astring SPACE] | ||
4011 | 1#search_key | ||
4012 | ;; [CHARSET] MUST be registered with IANA | ||
4013 | |||
4014 | search_key ::= "ALL" / "ANSWERED" / "BCC" SPACE astring / | ||
4015 | "BEFORE" SPACE date / "BODY" SPACE astring / | ||
4016 | "CC" SPACE astring / "DELETED" / "FLAGGED" / | ||
4017 | "FROM" SPACE astring / | ||
4018 | "KEYWORD" SPACE flag_keyword / "NEW" / "OLD" / | ||
4019 | "ON" SPACE date / "RECENT" / "SEEN" / | ||
4020 | "SINCE" SPACE date / "SUBJECT" SPACE astring / | ||
4021 | "TEXT" SPACE astring / "TO" SPACE astring / | ||
4022 | "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / | ||
4023 | "UNKEYWORD" SPACE flag_keyword / "UNSEEN" / | ||
4024 | ;; Above this line were in [IMAP2] | ||
4025 | "DRAFT" / | ||
4026 | "HEADER" SPACE header_fld_name SPACE astring / | ||
4027 | "LARGER" SPACE number / "NOT" SPACE search_key / | ||
4028 | "OR" SPACE search_key SPACE search_key / | ||
4029 | "SENTBEFORE" SPACE date / "SENTON" SPACE date / | ||
4030 | "SENTSINCE" SPACE date / "SMALLER" SPACE number / | ||
4031 | |||
4032 | |||
4033 | |||
4034 | Crispin Standards Track [Page 72] | ||
4035 | |||
4036 | RFC 2060 IMAP4rev1 December 1996 | ||
4037 | |||
4038 | |||
4039 | "UID" SPACE set / "UNDRAFT" / set / | ||
4040 | "(" 1#search_key ")" | ||
4041 | |||
4042 | section ::= "[" [section_text / (nz_number *["." nz_number] | ||
4043 | ["." (section_text / "MIME")])] "]" | ||
4044 | |||
4045 | section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"] | ||
4046 | SPACE header_list / "TEXT" | ||
4047 | |||
4048 | select ::= "SELECT" SPACE mailbox | ||
4049 | |||
4050 | sequence_num ::= nz_number / "*" | ||
4051 | ;; * is the largest number in use. For message | ||
4052 | ;; sequence numbers, it is the number of messages | ||
4053 | ;; in the mailbox. For unique identifiers, it is | ||
4054 | ;; the unique identifier of the last message in | ||
4055 | ;; the mailbox. | ||
4056 | |||
4057 | set ::= sequence_num / (sequence_num ":" sequence_num) / | ||
4058 | (set "," set) | ||
4059 | ;; Identifies a set of messages. For message | ||
4060 | ;; sequence numbers, these are consecutive | ||
4061 | ;; numbers from 1 to the number of messages in | ||
4062 | ;; the mailbox | ||
4063 | ;; Comma delimits individual numbers, colon | ||
4064 | ;; delimits between two numbers inclusive. | ||
4065 | ;; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, | ||
4066 | ;; 14,15 for a mailbox with 15 messages. | ||
4067 | |||
4068 | SPACE ::= <ASCII SP, space, 0x20> | ||
4069 | |||
4070 | status ::= "STATUS" SPACE mailbox SPACE "(" 1#status_att ")" | ||
4071 | |||
4072 | status_att ::= "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / | ||
4073 | "UNSEEN" | ||
4074 | |||
4075 | store ::= "STORE" SPACE set SPACE store_att_flags | ||
4076 | |||
4077 | store_att_flags ::= (["+" / "-"] "FLAGS" [".SILENT"]) SPACE | ||
4078 | (flag_list / #flag) | ||
4079 | |||
4080 | string ::= quoted / literal | ||
4081 | |||
4082 | subscribe ::= "SUBSCRIBE" SPACE mailbox | ||
4083 | |||
4084 | tag ::= 1*<any ATOM_CHAR except "+"> | ||
4085 | |||
4086 | text ::= 1*TEXT_CHAR | ||
4087 | |||
4088 | |||
4089 | |||
4090 | Crispin Standards Track [Page 73] | ||
4091 | |||
4092 | RFC 2060 IMAP4rev1 December 1996 | ||
4093 | |||
4094 | |||
4095 | text_mime2 ::= "=?" <charset> "?" <encoding> "?" | ||
4096 | <encoded-text> "?=" | ||
4097 | ;; Syntax defined in [MIME-HDRS] | ||
4098 | |||
4099 | TEXT_CHAR ::= <any CHAR except CR and LF> | ||
4100 | |||
4101 | time ::= 2digit ":" 2digit ":" 2digit | ||
4102 | ;; Hours minutes seconds | ||
4103 | |||
4104 | uid ::= "UID" SPACE (copy / fetch / search / store) | ||
4105 | ;; Unique identifiers used instead of message | ||
4106 | ;; sequence numbers | ||
4107 | |||
4108 | uniqueid ::= nz_number | ||
4109 | ;; Strictly ascending | ||
4110 | |||
4111 | unsubscribe ::= "UNSUBSCRIBE" SPACE mailbox | ||
4112 | |||
4113 | userid ::= astring | ||
4114 | |||
4115 | x_command ::= "X" atom <experimental command arguments> | ||
4116 | |||
4117 | zone ::= ("+" / "-") 4digit | ||
4118 | ;; Signed four-digit value of hhmm representing | ||
4119 | ;; hours and minutes west of Greenwich (that is, | ||
4120 | ;; (the amount that the given time differs from | ||
4121 | ;; Universal Time). Subtracting the timezone | ||
4122 | ;; from the given time will give the UT form. | ||
4123 | ;; The Universal Time zone is "+0000". | ||
4124 | |||
4125 | 10. Author's Note | ||
4126 | |||
4127 | This document is a revision or rewrite of earlier documents, and | ||
4128 | supercedes the protocol specification in those documents: RFC 1730, | ||
4129 | unpublished IMAP2bis.TXT document, RFC 1176, and RFC 1064. | ||
4130 | |||
4131 | 11. Security Considerations | ||
4132 | |||
4133 | IMAP4rev1 protocol transactions, including electronic mail data, are | ||
4134 | sent in the clear over the network unless privacy protection is | ||
4135 | negotiated in the AUTHENTICATE command. | ||
4136 | |||
4137 | A server error message for an AUTHENTICATE command which fails due to | ||
4138 | invalid credentials SHOULD NOT detail why the credentials are | ||
4139 | invalid. | ||
4140 | |||
4141 | Use of the LOGIN command sends passwords in the clear. This can be | ||
4142 | avoided by using the AUTHENTICATE command instead. | ||
4143 | |||
4144 | |||
4145 | |||
4146 | Crispin Standards Track [Page 74] | ||
4147 | |||
4148 | RFC 2060 IMAP4rev1 December 1996 | ||
4149 | |||
4150 | |||
4151 | A server error message for a failing LOGIN command SHOULD NOT specify | ||
4152 | that the user name, as opposed to the password, is invalid. | ||
4153 | |||
4154 | Additional security considerations are discussed in the section | ||
4155 | discussing the AUTHENTICATE and LOGIN commands. | ||
4156 | |||
4157 | 12. Author's Address | ||
4158 | |||
4159 | Mark R. Crispin | ||
4160 | Networks and Distributed Computing | ||
4161 | University of Washington | ||
4162 | 4545 15th Aveneue NE | ||
4163 | Seattle, WA 98105-4527 | ||
4164 | |||
4165 | Phone: (206) 543-5762 | ||
4166 | |||
4167 | EMail: MRC@CAC.Washington.EDU | ||
4168 | |||
4169 | |||
4170 | |||
4171 | |||
4172 | |||
4173 | |||
4174 | |||
4175 | |||
4176 | |||
4177 | |||
4178 | |||
4179 | |||
4180 | |||
4181 | |||
4182 | |||
4183 | |||
4184 | |||
4185 | |||
4186 | |||
4187 | |||
4188 | |||
4189 | |||
4190 | |||
4191 | |||
4192 | |||
4193 | |||
4194 | |||
4195 | |||
4196 | |||
4197 | |||
4198 | |||
4199 | |||
4200 | |||
4201 | |||
4202 | Crispin Standards Track [Page 75] | ||
4203 | |||
4204 | RFC 2060 IMAP4rev1 December 1996 | ||
4205 | |||
4206 | |||
4207 | Appendices | ||
4208 | |||
4209 | A. References | ||
4210 | |||
4211 | [ACAP] Myers, J. "ACAP -- Application Configuration Access Protocol", | ||
4212 | Work in Progress. | ||
4213 | |||
4214 | [CHARSET] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, | ||
4215 | RFC 1700, USC/Information Sciences Institute, October 1994. | ||
4216 | |||
4217 | [DISPOSITION] Troost, R., and Dorner, S., "Communicating Presentation | ||
4218 | Information in Internet Messages: The Content-Disposition Header", | ||
4219 | RFC 1806, June 1995. | ||
4220 | |||
4221 | [IMAP-AUTH] Myers, J., "IMAP4 Authentication Mechanism", RFC 1731. | ||
4222 | Carnegie-Mellon University, December 1994. | ||
4223 | |||
4224 | [IMAP-COMPAT] Crispin, M., "IMAP4 Compatibility with IMAP2bis", RFC | ||
4225 | 2061, University of Washington, November 1996. | ||
4226 | |||
4227 | [IMAP-DISC] Austein, R., "Synchronization Operations for Disconnected | ||
4228 | IMAP4 Clients", Work in Progress. | ||
4229 | |||
4230 | [IMAP-HISTORICAL] Crispin, M. "IMAP4 Compatibility with IMAP2 and | ||
4231 | IMAP2bis", RFC 1732, University of Washington, December 1994. | ||
4232 | |||
4233 | [IMAP-MODEL] Crispin, M., "Distributed Electronic Mail Models in | ||
4234 | IMAP4", RFC 1733, University of Washington, December 1994. | ||
4235 | |||
4236 | [IMAP-OBSOLETE] Crispin, M., "Internet Message Access Protocol - | ||
4237 | Obsolete Syntax", RFC 2062, University of Washington, November 1996. | ||
4238 | |||
4239 | [IMAP2] Crispin, M., "Interactive Mail Access Protocol - Version 2", | ||
4240 | RFC 1176, University of Washington, August 1990. | ||
4241 | |||
4242 | [LANGUAGE-TAGS] Alvestrand, H., "Tags for the Identification of | ||
4243 | Languages", RFC 1766, March 1995. | ||
4244 | |||
4245 | [MD5] Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC | ||
4246 | 1864, October 1995. | ||
4247 | |||
4248 | [MIME-IMB] Freed, N., and N. Borenstein, "MIME (Multipurpose Internet | ||
4249 | Mail Extensions) Part One: Format of Internet Message Bodies", RFC | ||
4250 | 2045, November 1996. | ||
4251 | |||
4252 | [MIME-IMT] Freed, N., and N. Borenstein, "MIME (Multipurpose | ||
4253 | Internet Mail Extensions) Part Two: Media Types", RFC 2046, | ||
4254 | November 1996. | ||
4255 | |||
4256 | |||
4257 | |||
4258 | Crispin Standards Track [Page 76] | ||
4259 | |||
4260 | RFC 2060 IMAP4rev1 December 1996 | ||
4261 | |||
4262 | |||
4263 | [MIME-HDRS] Moore, K., "MIME (Multipurpose Internet Mail Extensions) | ||
4264 | Part Three: Message Header Extensions for Non-ASCII Text", RFC | ||
4265 | 2047, November 1996. | ||
4266 | |||
4267 | [RFC-822] Crocker, D., "Standard for the Format of ARPA Internet Text | ||
4268 | Messages", STD 11, RFC 822, University of Delaware, August 1982. | ||
4269 | |||
4270 | [SMTP] Postel, J., "Simple Mail Transfer Protocol", STD 10, | ||
4271 | RFC 821, USC/Information Sciences Institute, August 1982. | ||
4272 | |||
4273 | [UTF-7] Goldsmith, D., and Davis, M., "UTF-7: A Mail-Safe | ||
4274 | Transformation Format of Unicode", RFC 1642, July 1994. | ||
4275 | |||
4276 | B. Changes from RFC 1730 | ||
4277 | |||
4278 | 1) The STATUS command has been added. | ||
4279 | |||
4280 | 2) Clarify in the formal syntax that the "#" construct can never | ||
4281 | refer to multiple spaces. | ||
4282 | |||
4283 | 3) Obsolete syntax has been moved to a separate document. | ||
4284 | |||
4285 | 4) The PARTIAL command has been obsoleted. | ||
4286 | |||
4287 | 5) The RFC822.HEADER.LINES, RFC822.HEADER.LINES.NOT, RFC822.PEEK, and | ||
4288 | RFC822.TEXT.PEEK fetch attributes have been obsoleted. | ||
4289 | |||
4290 | 6) The "<" origin "." size ">" suffix for BODY text attributes has | ||
4291 | been added. | ||
4292 | |||
4293 | 7) The HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, and TEXT part | ||
4294 | specifiers have been added. | ||
4295 | |||
4296 | 8) Support for Content-Disposition and Content-Language has been | ||
4297 | added. | ||
4298 | |||
4299 | 9) The restriction on fetching nested MULTIPART parts has been | ||
4300 | removed. | ||
4301 | |||
4302 | 10) Body part number 0 has been obsoleted. | ||
4303 | |||
4304 | 11) Server-supported authenticators are now identified by | ||
4305 | capabilities. | ||
4306 | |||
4307 | |||
4308 | |||
4309 | |||
4310 | |||
4311 | |||
4312 | |||
4313 | |||
4314 | Crispin Standards Track [Page 77] | ||
4315 | |||
4316 | RFC 2060 IMAP4rev1 December 1996 | ||
4317 | |||
4318 | |||
4319 | 12) The capability that identifies this protocol is now called | ||
4320 | "IMAP4rev1". A server that provides backwards support for RFC 1730 | ||
4321 | SHOULD emit the "IMAP4" capability in addition to "IMAP4rev1" in its | ||
4322 | CAPABILITY response. Because RFC-1730 required "IMAP4" to appear as | ||
4323 | the first capability, it MUST listed first in the response. | ||
4324 | |||
4325 | 13) A description of the mailbox name namespace convention has been | ||
4326 | added. | ||
4327 | |||
4328 | 14) A description of the international mailbox name convention has | ||
4329 | been added. | ||
4330 | |||
4331 | 15) The UID-NEXT and UID-VALIDITY status items are now called UIDNEXT | ||
4332 | and UIDVALIDITY. This is a change from the IMAP STATUS | ||
4333 | Work in Progress and not from RFC-1730 | ||
4334 | |||
4335 | 16) Add a clarification that a null mailbox name argument to the LIST | ||
4336 | command returns an untagged LIST response with the hierarchy | ||
4337 | delimiter and root of the reference argument. | ||
4338 | |||
4339 | 17) Define terms such as "MUST", "SHOULD", and "MUST NOT". | ||
4340 | |||
4341 | 18) Add a section which defines message attributes and more | ||
4342 | thoroughly details the semantics of message sequence numbers, UIDs, | ||
4343 | and flags. | ||
4344 | |||
4345 | 19) Add a clarification detailing the circumstances when a client may | ||
4346 | send multiple commands without waiting for a response, and the | ||
4347 | circumstances in which ambiguities may result. | ||
4348 | |||
4349 | 20) Add a recommendation on server behavior for DELETE and RENAME | ||
4350 | when inferior hierarchical names of the given name exist. | ||
4351 | |||
4352 | 21) Add a clarification that a mailbox name may not be unilaterally | ||
4353 | unsubscribed by the server, even if that mailbox name no longer | ||
4354 | exists. | ||
4355 | |||
4356 | 22) Add a clarification that LIST should return its results quickly | ||
4357 | without undue delay. | ||
4358 | |||
4359 | 23) Add a clarification that the date_time argument to APPEND sets | ||
4360 | the internal date of the message. | ||
4361 | |||
4362 | 24) Add a clarification on APPEND behavior when the target mailbox is | ||
4363 | the currently selected mailbox. | ||
4364 | |||
4365 | |||
4366 | |||
4367 | |||
4368 | |||
4369 | |||
4370 | Crispin Standards Track [Page 78] | ||
4371 | |||
4372 | RFC 2060 IMAP4rev1 December 1996 | ||
4373 | |||
4374 | |||
4375 | 25) Add a clarification that external changes to flags should be | ||
4376 | always announced via an untagged FETCH even if the current command is | ||
4377 | a STORE with the ".SILENT" suffix. | ||
4378 | |||
4379 | 26) Add a clarification that COPY appends to the target mailbox. | ||
4380 | |||
4381 | 27) Add the NEWNAME response code. | ||
4382 | |||
4383 | 28) Rewrite the description of the untagged BYE response to clarify | ||
4384 | its semantics. | ||
4385 | |||
4386 | 29) Change the reference for the body MD5 to refer to the proper RFC. | ||
4387 | |||
4388 | 30) Clarify that the formal syntax contains rules which may overlap, | ||
4389 | and that in the event of such an overlap the rule which occurs first | ||
4390 | takes precedence. | ||
4391 | |||
4392 | 31) Correct the definition of body_fld_param. | ||
4393 | |||
4394 | 32) More formal syntax for capability_data. | ||
4395 | |||
4396 | 33) Clarify that any case variant of "INBOX" must be interpreted as | ||
4397 | INBOX. | ||
4398 | |||
4399 | 34) Clarify that the human-readable text in resp_text should not | ||
4400 | begin with "[" or "=". | ||
4401 | |||
4402 | 35) Change MIME references to Draft Standard documents. | ||
4403 | |||
4404 | 36) Clarify \Recent semantics. | ||
4405 | |||
4406 | 37) Additional examples. | ||
4407 | |||
4408 | C. Key Word Index | ||
4409 | |||
4410 | +FLAGS <flag list> (store command data item) ............... 45 | ||
4411 | +FLAGS.SILENT <flag list> (store command data item) ........ 46 | ||
4412 | -FLAGS <flag list> (store command data item) ............... 46 | ||
4413 | -FLAGS.SILENT <flag list> (store command data item) ........ 46 | ||
4414 | ALERT (response code) ...................................... 50 | ||
4415 | ALL (fetch item) ........................................... 41 | ||
4416 | ALL (search key) ........................................... 38 | ||
4417 | ANSWERED (search key) ...................................... 38 | ||
4418 | APPEND (command) ........................................... 34 | ||
4419 | AUTHENTICATE (command) ..................................... 20 | ||
4420 | BAD (response) ............................................. 52 | ||
4421 | BCC <string> (search key) .................................. 38 | ||
4422 | BEFORE <date> (search key) ................................. 39 | ||
4423 | |||
4424 | |||
4425 | |||
4426 | Crispin Standards Track [Page 79] | ||
4427 | |||
4428 | RFC 2060 IMAP4rev1 December 1996 | ||
4429 | |||
4430 | |||
4431 | BODY (fetch item) .......................................... 41 | ||
4432 | BODY (fetch result) ........................................ 58 | ||
4433 | BODY <string> (search key) ................................. 39 | ||
4434 | BODY.PEEK[<section>]<<partial>> (fetch item) ............... 44 | ||
4435 | BODYSTRUCTURE (fetch item) ................................. 44 | ||
4436 | BODYSTRUCTURE (fetch result) ............................... 59 | ||
4437 | BODY[<section>]<<origin_octet>> (fetch result) ............. 58 | ||
4438 | BODY[<section>]<<partial>> (fetch item) .................... 41 | ||
4439 | BYE (response) ............................................. 52 | ||
4440 | Body Structure (message attribute) ......................... 11 | ||
4441 | CAPABILITY (command) ....................................... 18 | ||
4442 | CAPABILITY (response) ...................................... 53 | ||
4443 | CC <string> (search key) ................................... 39 | ||
4444 | CHECK (command) ............................................ 36 | ||
4445 | CLOSE (command) ............................................ 36 | ||
4446 | COPY (command) ............................................. 46 | ||
4447 | CREATE (command) ........................................... 25 | ||
4448 | DELETE (command) ........................................... 26 | ||
4449 | DELETED (search key) ....................................... 39 | ||
4450 | DRAFT (search key) ......................................... 39 | ||
4451 | ENVELOPE (fetch item) ...................................... 44 | ||
4452 | ENVELOPE (fetch result) .................................... 62 | ||
4453 | EXAMINE (command) .......................................... 24 | ||
4454 | EXISTS (response) .......................................... 56 | ||
4455 | EXPUNGE (command) .......................................... 37 | ||
4456 | EXPUNGE (response) ......................................... 57 | ||
4457 | Envelope Structure (message attribute) ..................... 11 | ||
4458 | FAST (fetch item) .......................................... 44 | ||
4459 | FETCH (command) ............................................ 41 | ||
4460 | FETCH (response) ........................................... 58 | ||
4461 | FLAGGED (search key) ....................................... 39 | ||
4462 | FLAGS (fetch item) ......................................... 44 | ||
4463 | FLAGS (fetch result) ....................................... 62 | ||
4464 | FLAGS (response) ........................................... 56 | ||
4465 | FLAGS <flag list> (store command data item) ................ 45 | ||
4466 | FLAGS.SILENT <flag list> (store command data item) ......... 45 | ||
4467 | FROM <string> (search key) ................................. 39 | ||
4468 | FULL (fetch item) .......................................... 44 | ||
4469 | Flags (message attribute) .................................. 9 | ||
4470 | HEADER (part specifier) .................................... 41 | ||
4471 | HEADER <field-name> <string> (search key) .................. 39 | ||
4472 | HEADER.FIELDS <header_list> (part specifier) ............... 41 | ||
4473 | HEADER.FIELDS.NOT <header_list> (part specifier) ........... 41 | ||
4474 | INTERNALDATE (fetch item) .................................. 44 | ||
4475 | INTERNALDATE (fetch result) ................................ 62 | ||
4476 | Internal Date (message attribute) .......................... 10 | ||
4477 | KEYWORD <flag> (search key) ................................ 39 | ||
4478 | Keyword (type of flag) ..................................... 10 | ||
4479 | |||
4480 | |||
4481 | |||
4482 | Crispin Standards Track [Page 80] | ||
4483 | |||
4484 | RFC 2060 IMAP4rev1 December 1996 | ||
4485 | |||
4486 | |||
4487 | LARGER <n> (search key) .................................... 39 | ||
4488 | LIST (command) ............................................. 30 | ||
4489 | LIST (response) ............................................ 54 | ||
4490 | LOGIN (command) ............................................ 22 | ||
4491 | LOGOUT (command) ........................................... 20 | ||
4492 | LSUB (command) ............................................. 32 | ||
4493 | LSUB (response) ............................................ 55 | ||
4494 | MAY (specification requirement term) ....................... 5 | ||
4495 | MESSAGES (status item) ..................................... 33 | ||
4496 | MIME (part specifier) ...................................... 42 | ||
4497 | MUST (specification requirement term) ...................... 4 | ||
4498 | MUST NOT (specification requirement term) .................. 4 | ||
4499 | Message Sequence Number (message attribute) ................ 9 | ||
4500 | NEW (search key) ........................................... 39 | ||
4501 | NEWNAME (response code) .................................... 50 | ||
4502 | NO (response) .............................................. 51 | ||
4503 | NOOP (command) ............................................. 19 | ||
4504 | NOT <search-key> (search key) .............................. 39 | ||
4505 | OK (response) .............................................. 51 | ||
4506 | OLD (search key) ........................................... 39 | ||
4507 | ON <date> (search key) ..................................... 39 | ||
4508 | OPTIONAL (specification requirement term) .................. 5 | ||
4509 | OR <search-key1> <search-key2> (search key) ................ 39 | ||
4510 | PARSE (response code) ...................................... 50 | ||
4511 | PERMANENTFLAGS (response code) ............................. 50 | ||
4512 | PREAUTH (response) ......................................... 52 | ||
4513 | Permanent Flag (class of flag) ............................. 10 | ||
4514 | READ-ONLY (response code) .................................. 50 | ||
4515 | READ-WRITE (response code) ................................. 50 | ||
4516 | RECENT (response) .......................................... 57 | ||
4517 | RECENT (search key) ........................................ 39 | ||
4518 | RECENT (status item) ....................................... 33 | ||
4519 | RENAME (command) ........................................... 27 | ||
4520 | REQUIRED (specification requirement term) .................. 4 | ||
4521 | RFC822 (fetch item) ........................................ 44 | ||
4522 | RFC822 (fetch result) ...................................... 63 | ||
4523 | RFC822.HEADER (fetch item) ................................. 44 | ||
4524 | RFC822.HEADER (fetch result) ............................... 62 | ||
4525 | RFC822.SIZE (fetch item) ................................... 44 | ||
4526 | RFC822.SIZE (fetch result) ................................. 62 | ||
4527 | RFC822.TEXT (fetch item) ................................... 44 | ||
4528 | RFC822.TEXT (fetch result) ................................. 62 | ||
4529 | SEARCH (command) ........................................... 37 | ||
4530 | SEARCH (response) .......................................... 55 | ||
4531 | SEEN (search key) .......................................... 40 | ||
4532 | SELECT (command) ........................................... 23 | ||
4533 | SENTBEFORE <date> (search key) ............................. 40 | ||
4534 | SENTON <date> (search key) ................................. 40 | ||
4535 | |||
4536 | |||
4537 | |||
4538 | Crispin Standards Track [Page 81] | ||
4539 | |||
4540 | RFC 2060 IMAP4rev1 December 1996 | ||
4541 | |||
4542 | |||
4543 | SENTSINCE <date> (search key) .............................. 40 | ||
4544 | SHOULD (specification requirement term) .................... 5 | ||
4545 | SHOULD NOT (specification requirement term) ................ 5 | ||
4546 | SINCE <date> (search key) .................................. 40 | ||
4547 | SMALLER <n> (search key) ................................... 40 | ||
4548 | STATUS (command) ........................................... 33 | ||
4549 | STATUS (response) .......................................... 55 | ||
4550 | STORE (command) ............................................ 45 | ||
4551 | SUBJECT <string> (search key) .............................. 40 | ||
4552 | SUBSCRIBE (command) ........................................ 29 | ||
4553 | Session Flag (class of flag) ............................... 10 | ||
4554 | System Flag (type of flag) ................................. 9 | ||
4555 | TEXT (part specifier) ...................................... 42 | ||
4556 | TEXT <string> (search key) ................................. 40 | ||
4557 | TO <string> (search key) ................................... 40 | ||
4558 | TRYCREATE (response code) .................................. 51 | ||
4559 | UID (command) .............................................. 47 | ||
4560 | UID (fetch item) ........................................... 44 | ||
4561 | UID (fetch result) ......................................... 63 | ||
4562 | UID <message set> (search key) ............................. 40 | ||
4563 | UIDNEXT (status item) ...................................... 33 | ||
4564 | UIDVALIDITY (response code) ................................ 51 | ||
4565 | UIDVALIDITY (status item) .................................. 34 | ||
4566 | UNANSWERED (search key) .................................... 40 | ||
4567 | UNDELETED (search key) ..................................... 40 | ||
4568 | UNDRAFT (search key) ....................................... 40 | ||
4569 | UNFLAGGED (search key) ..................................... 40 | ||
4570 | UNKEYWORD <flag> (search key) .............................. 40 | ||
4571 | UNSEEN (response code) ..................................... 51 | ||
4572 | UNSEEN (search key) ........................................ 40 | ||
4573 | UNSEEN (status item) ....................................... 34 | ||
4574 | UNSUBSCRIBE (command) ...................................... 30 | ||
4575 | Unique Identifier (UID) (message attribute) ................ 7 | ||
4576 | X<atom> (command) .......................................... 48 | ||
4577 | [RFC-822] Size (message attribute) ......................... 11 | ||
4578 | \Answered (system flag) .................................... 9 | ||
4579 | \Deleted (system flag) ..................................... 9 | ||
4580 | \Draft (system flag) ....................................... 9 | ||
4581 | \Flagged (system flag) ..................................... 9 | ||
4582 | \Marked (mailbox name attribute) ........................... 54 | ||
4583 | \Noinferiors (mailbox name attribute) ...................... 54 | ||
4584 | \Noselect (mailbox name attribute) ......................... 54 | ||
4585 | \Recent (system flag) ...................................... 10 | ||
4586 | \Seen (system flag) ........................................ 9 | ||
4587 | \Unmarked (mailbox name attribute) ......................... 54 | ||
4588 | |||
4589 | |||
4590 | |||
4591 | |||
4592 | |||
4593 | |||
4594 | Crispin Standards Track [Page 82] | ||
4595 | |||
diff --git a/misc/rfc2616-http.txt b/misc/rfc2616-http.txt new file mode 100644 index 0000000..45d7d08 --- /dev/null +++ b/misc/rfc2616-http.txt | |||
@@ -0,0 +1,9859 @@ | |||
1 | |||
2 | |||
3 | |||
4 | |||
5 | |||
6 | |||
7 | Network Working Group R. Fielding | ||
8 | Request for Comments: 2616 UC Irvine | ||
9 | Obsoletes: 2068 J. Gettys | ||
10 | Category: Standards Track Compaq/W3C | ||
11 | J. Mogul | ||
12 | Compaq | ||
13 | H. Frystyk | ||
14 | W3C/MIT | ||
15 | L. Masinter | ||
16 | Xerox | ||
17 | P. Leach | ||
18 | Microsoft | ||
19 | T. Berners-Lee | ||
20 | W3C/MIT | ||
21 | June 1999 | ||
22 | |||
23 | |||
24 | Hypertext Transfer Protocol -- HTTP/1.1 | ||
25 | |||
26 | Status of this Memo | ||
27 | |||
28 | This document specifies an Internet standards track protocol for the | ||
29 | Internet community, and requests discussion and suggestions for | ||
30 | improvements. Please refer to the current edition of the "Internet | ||
31 | Official Protocol Standards" (STD 1) for the standardization state | ||
32 | and status of this protocol. Distribution of this memo is unlimited. | ||
33 | |||
34 | Copyright Notice | ||
35 | |||
36 | Copyright (C) The Internet Society (1999). All Rights Reserved. | ||
37 | |||
38 | Abstract | ||
39 | |||
40 | The Hypertext Transfer Protocol (HTTP) is an application-level | ||
41 | protocol for distributed, collaborative, hypermedia information | ||
42 | systems. It is a generic, stateless, protocol which can be used for | ||
43 | many tasks beyond its use for hypertext, such as name servers and | ||
44 | distributed object management systems, through extension of its | ||
45 | request methods, error codes and headers [47]. A feature of HTTP is | ||
46 | the typing and negotiation of data representation, allowing systems | ||
47 | to be built independently of the data being transferred. | ||
48 | |||
49 | HTTP has been in use by the World-Wide Web global information | ||
50 | initiative since 1990. This specification defines the protocol | ||
51 | referred to as "HTTP/1.1", and is an update to RFC 2068 [33]. | ||
52 | |||
53 | |||
54 | |||
55 | |||
56 | |||
57 | |||
58 | Fielding, et al. Standards Track [Page 1] | ||
59 | |||
60 | RFC 2616 HTTP/1.1 June 1999 | ||
61 | |||
62 | |||
63 | Table of Contents | ||
64 | |||
65 | 1 Introduction ...................................................7 | ||
66 | 1.1 Purpose......................................................7 | ||
67 | 1.2 Requirements .................................................8 | ||
68 | 1.3 Terminology ..................................................8 | ||
69 | 1.4 Overall Operation ...........................................12 | ||
70 | 2 Notational Conventions and Generic Grammar ....................14 | ||
71 | 2.1 Augmented BNF ...............................................14 | ||
72 | 2.2 Basic Rules .................................................15 | ||
73 | 3 Protocol Parameters ...........................................17 | ||
74 | 3.1 HTTP Version ................................................17 | ||
75 | 3.2 Uniform Resource Identifiers ................................18 | ||
76 | 3.2.1 General Syntax ...........................................19 | ||
77 | 3.2.2 http URL .................................................19 | ||
78 | 3.2.3 URI Comparison ...........................................20 | ||
79 | 3.3 Date/Time Formats ...........................................20 | ||
80 | 3.3.1 Full Date ................................................20 | ||
81 | 3.3.2 Delta Seconds ............................................21 | ||
82 | 3.4 Character Sets ..............................................21 | ||
83 | 3.4.1 Missing Charset ..........................................22 | ||
84 | 3.5 Content Codings .............................................23 | ||
85 | 3.6 Transfer Codings ............................................24 | ||
86 | 3.6.1 Chunked Transfer Coding ..................................25 | ||
87 | 3.7 Media Types .................................................26 | ||
88 | 3.7.1 Canonicalization and Text Defaults .......................27 | ||
89 | 3.7.2 Multipart Types ..........................................27 | ||
90 | 3.8 Product Tokens ..............................................28 | ||
91 | 3.9 Quality Values ..............................................29 | ||
92 | 3.10 Language Tags ...............................................29 | ||
93 | 3.11 Entity Tags .................................................30 | ||
94 | 3.12 Range Units .................................................30 | ||
95 | 4 HTTP Message ..................................................31 | ||
96 | 4.1 Message Types ...............................................31 | ||
97 | 4.2 Message Headers .............................................31 | ||
98 | 4.3 Message Body ................................................32 | ||
99 | 4.4 Message Length ..............................................33 | ||
100 | 4.5 General Header Fields .......................................34 | ||
101 | 5 Request .......................................................35 | ||
102 | 5.1 Request-Line ................................................35 | ||
103 | 5.1.1 Method ...................................................36 | ||
104 | 5.1.2 Request-URI ..............................................36 | ||
105 | 5.2 The Resource Identified by a Request ........................38 | ||
106 | 5.3 Request Header Fields .......................................38 | ||
107 | 6 Response ......................................................39 | ||
108 | 6.1 Status-Line .................................................39 | ||
109 | 6.1.1 Status Code and Reason Phrase ............................39 | ||
110 | 6.2 Response Header Fields ......................................41 | ||
111 | |||
112 | |||
113 | |||
114 | Fielding, et al. Standards Track [Page 2] | ||
115 | |||
116 | RFC 2616 HTTP/1.1 June 1999 | ||
117 | |||
118 | |||
119 | 7 Entity ........................................................42 | ||
120 | 7.1 Entity Header Fields ........................................42 | ||
121 | 7.2 Entity Body .................................................43 | ||
122 | 7.2.1 Type .....................................................43 | ||
123 | 7.2.2 Entity Length ............................................43 | ||
124 | 8 Connections ...................................................44 | ||
125 | 8.1 Persistent Connections ......................................44 | ||
126 | 8.1.1 Purpose ..................................................44 | ||
127 | 8.1.2 Overall Operation ........................................45 | ||
128 | 8.1.3 Proxy Servers ............................................46 | ||
129 | 8.1.4 Practical Considerations .................................46 | ||
130 | 8.2 Message Transmission Requirements ...........................47 | ||
131 | 8.2.1 Persistent Connections and Flow Control ..................47 | ||
132 | 8.2.2 Monitoring Connections for Error Status Messages .........48 | ||
133 | 8.2.3 Use of the 100 (Continue) Status .........................48 | ||
134 | 8.2.4 Client Behavior if Server Prematurely Closes Connection ..50 | ||
135 | 9 Method Definitions ............................................51 | ||
136 | 9.1 Safe and Idempotent Methods .................................51 | ||
137 | 9.1.1 Safe Methods .............................................51 | ||
138 | 9.1.2 Idempotent Methods .......................................51 | ||
139 | 9.2 OPTIONS .....................................................52 | ||
140 | 9.3 GET .........................................................53 | ||
141 | 9.4 HEAD ........................................................54 | ||
142 | 9.5 POST ........................................................54 | ||
143 | 9.6 PUT .........................................................55 | ||
144 | 9.7 DELETE ......................................................56 | ||
145 | 9.8 TRACE .......................................................56 | ||
146 | 9.9 CONNECT .....................................................57 | ||
147 | 10 Status Code Definitions ......................................57 | ||
148 | 10.1 Informational 1xx ...........................................57 | ||
149 | 10.1.1 100 Continue .............................................58 | ||
150 | 10.1.2 101 Switching Protocols ..................................58 | ||
151 | 10.2 Successful 2xx ..............................................58 | ||
152 | 10.2.1 200 OK ...................................................58 | ||
153 | 10.2.2 201 Created ..............................................59 | ||
154 | 10.2.3 202 Accepted .............................................59 | ||
155 | 10.2.4 203 Non-Authoritative Information ........................59 | ||
156 | 10.2.5 204 No Content ...........................................60 | ||
157 | 10.2.6 205 Reset Content ........................................60 | ||
158 | 10.2.7 206 Partial Content ......................................60 | ||
159 | 10.3 Redirection 3xx .............................................61 | ||
160 | 10.3.1 300 Multiple Choices .....................................61 | ||
161 | 10.3.2 301 Moved Permanently ....................................62 | ||
162 | 10.3.3 302 Found ................................................62 | ||
163 | 10.3.4 303 See Other ............................................63 | ||
164 | 10.3.5 304 Not Modified .........................................63 | ||
165 | 10.3.6 305 Use Proxy ............................................64 | ||
166 | 10.3.7 306 (Unused) .............................................64 | ||
167 | |||
168 | |||
169 | |||
170 | Fielding, et al. Standards Track [Page 3] | ||
171 | |||
172 | RFC 2616 HTTP/1.1 June 1999 | ||
173 | |||
174 | |||
175 | 10.3.8 307 Temporary Redirect ...................................65 | ||
176 | 10.4 Client Error 4xx ............................................65 | ||
177 | 10.4.1 400 Bad Request .........................................65 | ||
178 | 10.4.2 401 Unauthorized ........................................66 | ||
179 | 10.4.3 402 Payment Required ....................................66 | ||
180 | 10.4.4 403 Forbidden ...........................................66 | ||
181 | 10.4.5 404 Not Found ...........................................66 | ||
182 | 10.4.6 405 Method Not Allowed ..................................66 | ||
183 | 10.4.7 406 Not Acceptable ......................................67 | ||
184 | 10.4.8 407 Proxy Authentication Required .......................67 | ||
185 | 10.4.9 408 Request Timeout .....................................67 | ||
186 | 10.4.10 409 Conflict ............................................67 | ||
187 | 10.4.11 410 Gone ................................................68 | ||
188 | 10.4.12 411 Length Required .....................................68 | ||
189 | 10.4.13 412 Precondition Failed .................................68 | ||
190 | 10.4.14 413 Request Entity Too Large ............................69 | ||
191 | 10.4.15 414 Request-URI Too Long ................................69 | ||
192 | 10.4.16 415 Unsupported Media Type ..............................69 | ||
193 | 10.4.17 416 Requested Range Not Satisfiable .....................69 | ||
194 | 10.4.18 417 Expectation Failed ..................................70 | ||
195 | 10.5 Server Error 5xx ............................................70 | ||
196 | 10.5.1 500 Internal Server Error ................................70 | ||
197 | 10.5.2 501 Not Implemented ......................................70 | ||
198 | 10.5.3 502 Bad Gateway ..........................................70 | ||
199 | 10.5.4 503 Service Unavailable ..................................70 | ||
200 | 10.5.5 504 Gateway Timeout ......................................71 | ||
201 | 10.5.6 505 HTTP Version Not Supported ...........................71 | ||
202 | 11 Access Authentication ........................................71 | ||
203 | 12 Content Negotiation ..........................................71 | ||
204 | 12.1 Server-driven Negotiation ...................................72 | ||
205 | 12.2 Agent-driven Negotiation ....................................73 | ||
206 | 12.3 Transparent Negotiation .....................................74 | ||
207 | 13 Caching in HTTP ..............................................74 | ||
208 | 13.1.1 Cache Correctness ........................................75 | ||
209 | 13.1.2 Warnings .................................................76 | ||
210 | 13.1.3 Cache-control Mechanisms .................................77 | ||
211 | 13.1.4 Explicit User Agent Warnings .............................78 | ||
212 | 13.1.5 Exceptions to the Rules and Warnings .....................78 | ||
213 | 13.1.6 Client-controlled Behavior ...............................79 | ||
214 | 13.2 Expiration Model ............................................79 | ||
215 | 13.2.1 Server-Specified Expiration ..............................79 | ||
216 | 13.2.2 Heuristic Expiration .....................................80 | ||
217 | 13.2.3 Age Calculations .........................................80 | ||
218 | 13.2.4 Expiration Calculations ..................................83 | ||
219 | 13.2.5 Disambiguating Expiration Values .........................84 | ||
220 | 13.2.6 Disambiguating Multiple Responses ........................84 | ||
221 | 13.3 Validation Model ............................................85 | ||
222 | 13.3.1 Last-Modified Dates ......................................86 | ||
223 | |||
224 | |||
225 | |||
226 | Fielding, et al. Standards Track [Page 4] | ||
227 | |||
228 | RFC 2616 HTTP/1.1 June 1999 | ||
229 | |||
230 | |||
231 | 13.3.2 Entity Tag Cache Validators ..............................86 | ||
232 | 13.3.3 Weak and Strong Validators ...............................86 | ||
233 | 13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates.89 | ||
234 | 13.3.5 Non-validating Conditionals ..............................90 | ||
235 | 13.4 Response Cacheability .......................................91 | ||
236 | 13.5 Constructing Responses From Caches ..........................92 | ||
237 | 13.5.1 End-to-end and Hop-by-hop Headers ........................92 | ||
238 | 13.5.2 Non-modifiable Headers ...................................92 | ||
239 | 13.5.3 Combining Headers ........................................94 | ||
240 | 13.5.4 Combining Byte Ranges ....................................95 | ||
241 | 13.6 Caching Negotiated Responses ................................95 | ||
242 | 13.7 Shared and Non-Shared Caches ................................96 | ||
243 | 13.8 Errors or Incomplete Response Cache Behavior ................97 | ||
244 | 13.9 Side Effects of GET and HEAD ................................97 | ||
245 | 13.10 Invalidation After Updates or Deletions ...................97 | ||
246 | 13.11 Write-Through Mandatory ...................................98 | ||
247 | 13.12 Cache Replacement .........................................99 | ||
248 | 13.13 History Lists .............................................99 | ||
249 | 14 Header Field Definitions ....................................100 | ||
250 | 14.1 Accept .....................................................100 | ||
251 | 14.2 Accept-Charset .............................................102 | ||
252 | 14.3 Accept-Encoding ............................................102 | ||
253 | 14.4 Accept-Language ............................................104 | ||
254 | 14.5 Accept-Ranges ..............................................105 | ||
255 | 14.6 Age ........................................................106 | ||
256 | 14.7 Allow ......................................................106 | ||
257 | 14.8 Authorization ..............................................107 | ||
258 | 14.9 Cache-Control ..............................................108 | ||
259 | 14.9.1 What is Cacheable .......................................109 | ||
260 | 14.9.2 What May be Stored by Caches ............................110 | ||
261 | 14.9.3 Modifications of the Basic Expiration Mechanism .........111 | ||
262 | 14.9.4 Cache Revalidation and Reload Controls ..................113 | ||
263 | 14.9.5 No-Transform Directive ..................................115 | ||
264 | 14.9.6 Cache Control Extensions ................................116 | ||
265 | 14.10 Connection ...............................................117 | ||
266 | 14.11 Content-Encoding .........................................118 | ||
267 | 14.12 Content-Language .........................................118 | ||
268 | 14.13 Content-Length ...........................................119 | ||
269 | 14.14 Content-Location .........................................120 | ||
270 | 14.15 Content-MD5 ..............................................121 | ||
271 | 14.16 Content-Range ............................................122 | ||
272 | 14.17 Content-Type .............................................124 | ||
273 | 14.18 Date .....................................................124 | ||
274 | 14.18.1 Clockless Origin Server Operation ......................125 | ||
275 | 14.19 ETag .....................................................126 | ||
276 | 14.20 Expect ...................................................126 | ||
277 | 14.21 Expires ..................................................127 | ||
278 | 14.22 From .....................................................128 | ||
279 | |||
280 | |||
281 | |||
282 | Fielding, et al. Standards Track [Page 5] | ||
283 | |||
284 | RFC 2616 HTTP/1.1 June 1999 | ||
285 | |||
286 | |||
287 | 14.23 Host .....................................................128 | ||
288 | 14.24 If-Match .................................................129 | ||
289 | 14.25 If-Modified-Since ........................................130 | ||
290 | 14.26 If-None-Match ............................................132 | ||
291 | 14.27 If-Range .................................................133 | ||
292 | 14.28 If-Unmodified-Since ......................................134 | ||
293 | 14.29 Last-Modified ............................................134 | ||
294 | 14.30 Location .................................................135 | ||
295 | 14.31 Max-Forwards .............................................136 | ||
296 | 14.32 Pragma ...................................................136 | ||
297 | 14.33 Proxy-Authenticate .......................................137 | ||
298 | 14.34 Proxy-Authorization ......................................137 | ||
299 | 14.35 Range ....................................................138 | ||
300 | 14.35.1 Byte Ranges ...........................................138 | ||
301 | 14.35.2 Range Retrieval Requests ..............................139 | ||
302 | 14.36 Referer ..................................................140 | ||
303 | 14.37 Retry-After ..............................................141 | ||
304 | 14.38 Server ...................................................141 | ||
305 | 14.39 TE .......................................................142 | ||
306 | 14.40 Trailer ..................................................143 | ||
307 | 14.41 Transfer-Encoding..........................................143 | ||
308 | 14.42 Upgrade ..................................................144 | ||
309 | 14.43 User-Agent ...............................................145 | ||
310 | 14.44 Vary .....................................................145 | ||
311 | 14.45 Via ......................................................146 | ||
312 | 14.46 Warning ..................................................148 | ||
313 | 14.47 WWW-Authenticate .........................................150 | ||
314 | 15 Security Considerations .......................................150 | ||
315 | 15.1 Personal Information....................................151 | ||
316 | 15.1.1 Abuse of Server Log Information .........................151 | ||
317 | 15.1.2 Transfer of Sensitive Information .......................151 | ||
318 | 15.1.3 Encoding Sensitive Information in URI's .................152 | ||
319 | 15.1.4 Privacy Issues Connected to Accept Headers ..............152 | ||
320 | 15.2 Attacks Based On File and Path Names .......................153 | ||
321 | 15.3 DNS Spoofing ...............................................154 | ||
322 | 15.4 Location Headers and Spoofing ..............................154 | ||
323 | 15.5 Content-Disposition Issues .................................154 | ||
324 | 15.6 Authentication Credentials and Idle Clients ................155 | ||
325 | 15.7 Proxies and Caching ........................................155 | ||
326 | 15.7.1 Denial of Service Attacks on Proxies....................156 | ||
327 | 16 Acknowledgments .............................................156 | ||
328 | 17 References ..................................................158 | ||
329 | 18 Authors' Addresses ..........................................162 | ||
330 | 19 Appendices ..................................................164 | ||
331 | 19.1 Internet Media Type message/http and application/http ......164 | ||
332 | 19.2 Internet Media Type multipart/byteranges ...................165 | ||
333 | 19.3 Tolerant Applications ......................................166 | ||
334 | 19.4 Differences Between HTTP Entities and RFC 2045 Entities ....167 | ||
335 | |||
336 | |||
337 | |||
338 | Fielding, et al. Standards Track [Page 6] | ||
339 | |||
340 | RFC 2616 HTTP/1.1 June 1999 | ||
341 | |||
342 | |||
343 | 19.4.1 MIME-Version ............................................167 | ||
344 | 19.4.2 Conversion to Canonical Form ............................167 | ||
345 | 19.4.3 Conversion of Date Formats ..............................168 | ||
346 | 19.4.4 Introduction of Content-Encoding ........................168 | ||
347 | 19.4.5 No Content-Transfer-Encoding ............................168 | ||
348 | 19.4.6 Introduction of Transfer-Encoding .......................169 | ||
349 | 19.4.7 MHTML and Line Length Limitations .......................169 | ||
350 | 19.5 Additional Features ........................................169 | ||
351 | 19.5.1 Content-Disposition .....................................170 | ||
352 | 19.6 Compatibility with Previous Versions .......................170 | ||
353 | 19.6.1 Changes from HTTP/1.0 ...................................171 | ||
354 | 19.6.2 Compatibility with HTTP/1.0 Persistent Connections ......172 | ||
355 | 19.6.3 Changes from RFC 2068 ...................................172 | ||
356 | 20 Index .......................................................175 | ||
357 | 21 Full Copyright Statement ....................................176 | ||
358 | |||
359 | 1 Introduction | ||
360 | |||
361 | 1.1 Purpose | ||
362 | |||
363 | The Hypertext Transfer Protocol (HTTP) is an application-level | ||
364 | protocol for distributed, collaborative, hypermedia information | ||
365 | systems. HTTP has been in use by the World-Wide Web global | ||
366 | information initiative since 1990. The first version of HTTP, | ||
367 | referred to as HTTP/0.9, was a simple protocol for raw data transfer | ||
368 | across the Internet. HTTP/1.0, as defined by RFC 1945 [6], improved | ||
369 | the protocol by allowing messages to be in the format of MIME-like | ||
370 | messages, containing metainformation about the data transferred and | ||
371 | modifiers on the request/response semantics. However, HTTP/1.0 does | ||
372 | not sufficiently take into consideration the effects of hierarchical | ||
373 | proxies, caching, the need for persistent connections, or virtual | ||
374 | hosts. In addition, the proliferation of incompletely-implemented | ||
375 | applications calling themselves "HTTP/1.0" has necessitated a | ||
376 | protocol version change in order for two communicating applications | ||
377 | to determine each other's true capabilities. | ||
378 | |||
379 | This specification defines the protocol referred to as "HTTP/1.1". | ||
380 | This protocol includes more stringent requirements than HTTP/1.0 in | ||
381 | order to ensure reliable implementation of its features. | ||
382 | |||
383 | Practical information systems require more functionality than simple | ||
384 | retrieval, including search, front-end update, and annotation. HTTP | ||
385 | allows an open-ended set of methods and headers that indicate the | ||
386 | purpose of a request [47]. It builds on the discipline of reference | ||
387 | provided by the Uniform Resource Identifier (URI) [3], as a location | ||
388 | (URL) [4] or name (URN) [20], for indicating the resource to which a | ||
389 | |||
390 | |||
391 | |||
392 | |||
393 | |||
394 | Fielding, et al. Standards Track [Page 7] | ||
395 | |||
396 | RFC 2616 HTTP/1.1 June 1999 | ||
397 | |||
398 | |||
399 | method is to be applied. Messages are passed in a format similar to | ||
400 | that used by Internet mail [9] as defined by the Multipurpose | ||
401 | Internet Mail Extensions (MIME) [7]. | ||
402 | |||
403 | HTTP is also used as a generic protocol for communication between | ||
404 | user agents and proxies/gateways to other Internet systems, including | ||
405 | those supported by the SMTP [16], NNTP [13], FTP [18], Gopher [2], | ||
406 | and WAIS [10] protocols. In this way, HTTP allows basic hypermedia | ||
407 | access to resources available from diverse applications. | ||
408 | |||
409 | 1.2 Requirements | ||
410 | |||
411 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | ||
412 | "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this | ||
413 | document are to be interpreted as described in RFC 2119 [34]. | ||
414 | |||
415 | An implementation is not compliant if it fails to satisfy one or more | ||
416 | of the MUST or REQUIRED level requirements for the protocols it | ||
417 | implements. An implementation that satisfies all the MUST or REQUIRED | ||
418 | level and all the SHOULD level requirements for its protocols is said | ||
419 | to be "unconditionally compliant"; one that satisfies all the MUST | ||
420 | level requirements but not all the SHOULD level requirements for its | ||
421 | protocols is said to be "conditionally compliant." | ||
422 | |||
423 | 1.3 Terminology | ||
424 | |||
425 | This specification uses a number of terms to refer to the roles | ||
426 | played by participants in, and objects of, the HTTP communication. | ||
427 | |||
428 | connection | ||
429 | A transport layer virtual circuit established between two programs | ||
430 | for the purpose of communication. | ||
431 | |||
432 | message | ||
433 | The basic unit of HTTP communication, consisting of a structured | ||
434 | sequence of octets matching the syntax defined in section 4 and | ||
435 | transmitted via the connection. | ||
436 | |||
437 | request | ||
438 | An HTTP request message, as defined in section 5. | ||
439 | |||
440 | response | ||
441 | An HTTP response message, as defined in section 6. | ||
442 | |||
443 | |||
444 | |||
445 | |||
446 | |||
447 | |||
448 | |||
449 | |||
450 | Fielding, et al. Standards Track [Page 8] | ||
451 | |||
452 | RFC 2616 HTTP/1.1 June 1999 | ||
453 | |||
454 | |||
455 | resource | ||
456 | A network data object or service that can be identified by a URI, | ||
457 | as defined in section 3.2. Resources may be available in multiple | ||
458 | representations (e.g. multiple languages, data formats, size, and | ||
459 | resolutions) or vary in other ways. | ||
460 | |||
461 | entity | ||
462 | The information transferred as the payload of a request or | ||
463 | response. An entity consists of metainformation in the form of | ||
464 | entity-header fields and content in the form of an entity-body, as | ||
465 | described in section 7. | ||
466 | |||
467 | representation | ||
468 | An entity included with a response that is subject to content | ||
469 | negotiation, as described in section 12. There may exist multiple | ||
470 | representations associated with a particular response status. | ||
471 | |||
472 | content negotiation | ||
473 | The mechanism for selecting the appropriate representation when | ||
474 | servicing a request, as described in section 12. The | ||
475 | representation of entities in any response can be negotiated | ||
476 | (including error responses). | ||
477 | |||
478 | variant | ||
479 | A resource may have one, or more than one, representation(s) | ||
480 | associated with it at any given instant. Each of these | ||
481 | representations is termed a `varriant'. Use of the term `variant' | ||
482 | does not necessarily imply that the resource is subject to content | ||
483 | negotiation. | ||
484 | |||
485 | client | ||
486 | A program that establishes connections for the purpose of sending | ||
487 | requests. | ||
488 | |||
489 | user agent | ||
490 | The client which initiates a request. These are often browsers, | ||
491 | editors, spiders (web-traversing robots), or other end user tools. | ||
492 | |||
493 | server | ||
494 | An application program that accepts connections in order to | ||
495 | service requests by sending back responses. Any given program may | ||
496 | be capable of being both a client and a server; our use of these | ||
497 | terms refers only to the role being performed by the program for a | ||
498 | particular connection, rather than to the program's capabilities | ||
499 | in general. Likewise, any server may act as an origin server, | ||
500 | proxy, gateway, or tunnel, switching behavior based on the nature | ||
501 | of each request. | ||
502 | |||
503 | |||
504 | |||
505 | |||
506 | Fielding, et al. Standards Track [Page 9] | ||
507 | |||
508 | RFC 2616 HTTP/1.1 June 1999 | ||
509 | |||
510 | |||
511 | origin server | ||
512 | The server on which a given resource resides or is to be created. | ||
513 | |||
514 | proxy | ||
515 | An intermediary program which acts as both a server and a client | ||
516 | for the purpose of making requests on behalf of other clients. | ||
517 | Requests are serviced internally or by passing them on, with | ||
518 | possible translation, to other servers. A proxy MUST implement | ||
519 | both the client and server requirements of this specification. A | ||
520 | "transparent proxy" is a proxy that does not modify the request or | ||
521 | response beyond what is required for proxy authentication and | ||
522 | identification. A "non-transparent proxy" is a proxy that modifies | ||
523 | the request or response in order to provide some added service to | ||
524 | the user agent, such as group annotation services, media type | ||
525 | transformation, protocol reduction, or anonymity filtering. Except | ||
526 | where either transparent or non-transparent behavior is explicitly | ||
527 | stated, the HTTP proxy requirements apply to both types of | ||
528 | proxies. | ||
529 | |||
530 | gateway | ||
531 | A server which acts as an intermediary for some other server. | ||
532 | Unlike a proxy, a gateway receives requests as if it were the | ||
533 | origin server for the requested resource; the requesting client | ||
534 | may not be aware that it is communicating with a gateway. | ||
535 | |||
536 | tunnel | ||
537 | An intermediary program which is acting as a blind relay between | ||
538 | two connections. Once active, a tunnel is not considered a party | ||
539 | to the HTTP communication, though the tunnel may have been | ||
540 | initiated by an HTTP request. The tunnel ceases to exist when both | ||
541 | ends of the relayed connections are closed. | ||
542 | |||
543 | cache | ||
544 | A program's local store of response messages and the subsystem | ||
545 | that controls its message storage, retrieval, and deletion. A | ||
546 | cache stores cacheable responses in order to reduce the response | ||
547 | time and network bandwidth consumption on future, equivalent | ||
548 | requests. Any client or server may include a cache, though a cache | ||
549 | cannot be used by a server that is acting as a tunnel. | ||
550 | |||
551 | cacheable | ||
552 | A response is cacheable if a cache is allowed to store a copy of | ||
553 | the response message for use in answering subsequent requests. The | ||
554 | rules for determining the cacheability of HTTP responses are | ||
555 | defined in section 13. Even if a resource is cacheable, there may | ||
556 | be additional constraints on whether a cache can use the cached | ||
557 | copy for a particular request. | ||
558 | |||
559 | |||
560 | |||
561 | |||
562 | Fielding, et al. Standards Track [Page 10] | ||
563 | |||
564 | RFC 2616 HTTP/1.1 June 1999 | ||
565 | |||
566 | |||
567 | first-hand | ||
568 | A response is first-hand if it comes directly and without | ||
569 | unnecessary delay from the origin server, perhaps via one or more | ||
570 | proxies. A response is also first-hand if its validity has just | ||
571 | been checked directly with the origin server. | ||
572 | |||
573 | explicit expiration time | ||
574 | The time at which the origin server intends that an entity should | ||
575 | no longer be returned by a cache without further validation. | ||
576 | |||
577 | heuristic expiration time | ||
578 | An expiration time assigned by a cache when no explicit expiration | ||
579 | time is available. | ||
580 | |||
581 | age | ||
582 | The age of a response is the time since it was sent by, or | ||
583 | successfully validated with, the origin server. | ||
584 | |||
585 | freshness lifetime | ||
586 | The length of time between the generation of a response and its | ||
587 | expiration time. | ||
588 | |||
589 | fresh | ||
590 | A response is fresh if its age has not yet exceeded its freshness | ||
591 | lifetime. | ||
592 | |||
593 | stale | ||
594 | A response is stale if its age has passed its freshness lifetime. | ||
595 | |||
596 | semantically transparent | ||
597 | A cache behaves in a "semantically transparent" manner, with | ||
598 | respect to a particular response, when its use affects neither the | ||
599 | requesting client nor the origin server, except to improve | ||
600 | performance. When a cache is semantically transparent, the client | ||
601 | receives exactly the same response (except for hop-by-hop headers) | ||
602 | that it would have received had its request been handled directly | ||
603 | by the origin server. | ||
604 | |||
605 | validator | ||
606 | A protocol element (e.g., an entity tag or a Last-Modified time) | ||
607 | that is used to find out whether a cache entry is an equivalent | ||
608 | copy of an entity. | ||
609 | |||
610 | upstream/downstream | ||
611 | Upstream and downstream describe the flow of a message: all | ||
612 | messages flow from upstream to downstream. | ||
613 | |||
614 | |||
615 | |||
616 | |||
617 | |||
618 | Fielding, et al. Standards Track [Page 11] | ||
619 | |||
620 | RFC 2616 HTTP/1.1 June 1999 | ||
621 | |||
622 | |||
623 | inbound/outbound | ||
624 | Inbound and outbound refer to the request and response paths for | ||
625 | messages: "inbound" means "traveling toward the origin server", | ||
626 | and "outbound" means "traveling toward the user agent" | ||
627 | |||
628 | 1.4 Overall Operation | ||
629 | |||
630 | The HTTP protocol is a request/response protocol. A client sends a | ||
631 | request to the server in the form of a request method, URI, and | ||
632 | protocol version, followed by a MIME-like message containing request | ||
633 | modifiers, client information, and possible body content over a | ||
634 | connection with a server. The server responds with a status line, | ||
635 | including the message's protocol version and a success or error code, | ||
636 | followed by a MIME-like message containing server information, entity | ||
637 | metainformation, and possible entity-body content. The relationship | ||
638 | between HTTP and MIME is described in appendix 19.4. | ||
639 | |||
640 | Most HTTP communication is initiated by a user agent and consists of | ||
641 | a request to be applied to a resource on some origin server. In the | ||
642 | simplest case, this may be accomplished via a single connection (v) | ||
643 | between the user agent (UA) and the origin server (O). | ||
644 | |||
645 | request chain ------------------------> | ||
646 | UA -------------------v------------------- O | ||
647 | <----------------------- response chain | ||
648 | |||
649 | A more complicated situation occurs when one or more intermediaries | ||
650 | are present in the request/response chain. There are three common | ||
651 | forms of intermediary: proxy, gateway, and tunnel. A proxy is a | ||
652 | forwarding agent, receiving requests for a URI in its absolute form, | ||
653 | rewriting all or part of the message, and forwarding the reformatted | ||
654 | request toward the server identified by the URI. A gateway is a | ||
655 | receiving agent, acting as a layer above some other server(s) and, if | ||
656 | necessary, translating the requests to the underlying server's | ||
657 | protocol. A tunnel acts as a relay point between two connections | ||
658 | without changing the messages; tunnels are used when the | ||
659 | communication needs to pass through an intermediary (such as a | ||
660 | firewall) even when the intermediary cannot understand the contents | ||
661 | of the messages. | ||
662 | |||
663 | request chain --------------------------------------> | ||
664 | UA -----v----- A -----v----- B -----v----- C -----v----- O | ||
665 | <------------------------------------- response chain | ||
666 | |||
667 | The figure above shows three intermediaries (A, B, and C) between the | ||
668 | user agent and origin server. A request or response message that | ||
669 | travels the whole chain will pass through four separate connections. | ||
670 | This distinction is important because some HTTP communication options | ||
671 | |||
672 | |||
673 | |||
674 | Fielding, et al. Standards Track [Page 12] | ||
675 | |||
676 | RFC 2616 HTTP/1.1 June 1999 | ||
677 | |||
678 | |||
679 | may apply only to the connection with the nearest, non-tunnel | ||
680 | neighbor, only to the end-points of the chain, or to all connections | ||
681 | along the chain. Although the diagram is linear, each participant may | ||
682 | be engaged in multiple, simultaneous communications. For example, B | ||
683 | may be receiving requests from many clients other than A, and/or | ||
684 | forwarding requests to servers other than C, at the same time that it | ||
685 | is handling A's request. | ||
686 | |||
687 | Any party to the communication which is not acting as a tunnel may | ||
688 | employ an internal cache for handling requests. The effect of a cache | ||
689 | is that the request/response chain is shortened if one of the | ||
690 | participants along the chain has a cached response applicable to that | ||
691 | request. The following illustrates the resulting chain if B has a | ||
692 | cached copy of an earlier response from O (via C) for a request which | ||
693 | has not been cached by UA or A. | ||
694 | |||
695 | request chain ----------> | ||
696 | UA -----v----- A -----v----- B - - - - - - C - - - - - - O | ||
697 | <--------- response chain | ||
698 | |||
699 | Not all responses are usefully cacheable, and some requests may | ||
700 | contain modifiers which place special requirements on cache behavior. | ||
701 | HTTP requirements for cache behavior and cacheable responses are | ||
702 | defined in section 13. | ||
703 | |||
704 | In fact, there are a wide variety of architectures and configurations | ||
705 | of caches and proxies currently being experimented with or deployed | ||
706 | across the World Wide Web. These systems include national hierarchies | ||
707 | of proxy caches to save transoceanic bandwidth, systems that | ||
708 | broadcast or multicast cache entries, organizations that distribute | ||
709 | subsets of cached data via CD-ROM, and so on. HTTP systems are used | ||
710 | in corporate intranets over high-bandwidth links, and for access via | ||
711 | PDAs with low-power radio links and intermittent connectivity. The | ||
712 | goal of HTTP/1.1 is to support the wide diversity of configurations | ||
713 | already deployed while introducing protocol constructs that meet the | ||
714 | needs of those who build web applications that require high | ||
715 | reliability and, failing that, at least reliable indications of | ||
716 | failure. | ||
717 | |||
718 | HTTP communication usually takes place over TCP/IP connections. The | ||
719 | default port is TCP 80 [19], but other ports can be used. This does | ||
720 | not preclude HTTP from being implemented on top of any other protocol | ||
721 | on the Internet, or on other networks. HTTP only presumes a reliable | ||
722 | transport; any protocol that provides such guarantees can be used; | ||
723 | the mapping of the HTTP/1.1 request and response structures onto the | ||
724 | transport data units of the protocol in question is outside the scope | ||
725 | of this specification. | ||
726 | |||
727 | |||
728 | |||
729 | |||
730 | Fielding, et al. Standards Track [Page 13] | ||
731 | |||
732 | RFC 2616 HTTP/1.1 June 1999 | ||
733 | |||
734 | |||
735 | In HTTP/1.0, most implementations used a new connection for each | ||
736 | request/response exchange. In HTTP/1.1, a connection may be used for | ||
737 | one or more request/response exchanges, although connections may be | ||
738 | closed for a variety of reasons (see section 8.1). | ||
739 | |||
740 | 2 Notational Conventions and Generic Grammar | ||
741 | |||
742 | 2.1 Augmented BNF | ||
743 | |||
744 | All of the mechanisms specified in this document are described in | ||
745 | both prose and an augmented Backus-Naur Form (BNF) similar to that | ||
746 | used by RFC 822 [9]. Implementors will need to be familiar with the | ||
747 | notation in order to understand this specification. The augmented BNF | ||
748 | includes the following constructs: | ||
749 | |||
750 | name = definition | ||
751 | The name of a rule is simply the name itself (without any | ||
752 | enclosing "<" and ">") and is separated from its definition by the | ||
753 | equal "=" character. White space is only significant in that | ||
754 | indentation of continuation lines is used to indicate a rule | ||
755 | definition that spans more than one line. Certain basic rules are | ||
756 | in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle | ||
757 | brackets are used within definitions whenever their presence will | ||
758 | facilitate discerning the use of rule names. | ||
759 | |||
760 | "literal" | ||
761 | Quotation marks surround literal text. Unless stated otherwise, | ||
762 | the text is case-insensitive. | ||
763 | |||
764 | rule1 | rule2 | ||
765 | Elements separated by a bar ("|") are alternatives, e.g., "yes | | ||
766 | no" will accept yes or no. | ||
767 | |||
768 | (rule1 rule2) | ||
769 | Elements enclosed in parentheses are treated as a single element. | ||
770 | Thus, "(elem (foo | bar) elem)" allows the token sequences "elem | ||
771 | foo elem" and "elem bar elem". | ||
772 | |||
773 | *rule | ||
774 | The character "*" preceding an element indicates repetition. The | ||
775 | full form is "<n>*<m>element" indicating at least <n> and at most | ||
776 | <m> occurrences of element. Default values are 0 and infinity so | ||
777 | that "*(element)" allows any number, including zero; "1*element" | ||
778 | requires at least one; and "1*2element" allows one or two. | ||
779 | |||
780 | [rule] | ||
781 | Square brackets enclose optional elements; "[foo bar]" is | ||
782 | equivalent to "*1(foo bar)". | ||
783 | |||
784 | |||
785 | |||
786 | Fielding, et al. Standards Track [Page 14] | ||
787 | |||
788 | RFC 2616 HTTP/1.1 June 1999 | ||
789 | |||
790 | |||
791 | N rule | ||
792 | Specific repetition: "<n>(element)" is equivalent to | ||
793 | "<n>*<n>(element)"; that is, exactly <n> occurrences of (element). | ||
794 | Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three | ||
795 | alphabetic characters. | ||
796 | |||
797 | #rule | ||
798 | A construct "#" is defined, similar to "*", for defining lists of | ||
799 | elements. The full form is "<n>#<m>element" indicating at least | ||
800 | <n> and at most <m> elements, each separated by one or more commas | ||
801 | (",") and OPTIONAL linear white space (LWS). This makes the usual | ||
802 | form of lists very easy; a rule such as | ||
803 | ( *LWS element *( *LWS "," *LWS element )) | ||
804 | can be shown as | ||
805 | 1#element | ||
806 | Wherever this construct is used, null elements are allowed, but do | ||
807 | not contribute to the count of elements present. That is, | ||
808 | "(element), , (element) " is permitted, but counts as only two | ||
809 | elements. Therefore, where at least one element is required, at | ||
810 | least one non-null element MUST be present. Default values are 0 | ||
811 | and infinity so that "#element" allows any number, including zero; | ||
812 | "1#element" requires at least one; and "1#2element" allows one or | ||
813 | two. | ||
814 | |||
815 | ; comment | ||
816 | A semi-colon, set off some distance to the right of rule text, | ||
817 | starts a comment that continues to the end of line. This is a | ||
818 | simple way of including useful notes in parallel with the | ||
819 | specifications. | ||
820 | |||
821 | implied *LWS | ||
822 | The grammar described by this specification is word-based. Except | ||
823 | where noted otherwise, linear white space (LWS) can be included | ||
824 | between any two adjacent words (token or quoted-string), and | ||
825 | between adjacent words and separators, without changing the | ||
826 | interpretation of a field. At least one delimiter (LWS and/or | ||
827 | |||
828 | separators) MUST exist between any two tokens (for the definition | ||
829 | of "token" below), since they would otherwise be interpreted as a | ||
830 | single token. | ||
831 | |||
832 | 2.2 Basic Rules | ||
833 | |||
834 | The following rules are used throughout this specification to | ||
835 | describe basic parsing constructs. The US-ASCII coded character set | ||
836 | is defined by ANSI X3.4-1986 [21]. | ||
837 | |||
838 | |||
839 | |||
840 | |||
841 | |||
842 | Fielding, et al. Standards Track [Page 15] | ||
843 | |||
844 | RFC 2616 HTTP/1.1 June 1999 | ||
845 | |||
846 | |||
847 | OCTET = <any 8-bit sequence of data> | ||
848 | CHAR = <any US-ASCII character (octets 0 - 127)> | ||
849 | UPALPHA = <any US-ASCII uppercase letter "A".."Z"> | ||
850 | LOALPHA = <any US-ASCII lowercase letter "a".."z"> | ||
851 | ALPHA = UPALPHA | LOALPHA | ||
852 | DIGIT = <any US-ASCII digit "0".."9"> | ||
853 | CTL = <any US-ASCII control character | ||
854 | (octets 0 - 31) and DEL (127)> | ||
855 | CR = <US-ASCII CR, carriage return (13)> | ||
856 | LF = <US-ASCII LF, linefeed (10)> | ||
857 | SP = <US-ASCII SP, space (32)> | ||
858 | HT = <US-ASCII HT, horizontal-tab (9)> | ||
859 | <"> = <US-ASCII double-quote mark (34)> | ||
860 | |||
861 | HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all | ||
862 | protocol elements except the entity-body (see appendix 19.3 for | ||
863 | tolerant applications). The end-of-line marker within an entity-body | ||
864 | is defined by its associated media type, as described in section 3.7. | ||
865 | |||
866 | CRLF = CR LF | ||
867 | |||
868 | HTTP/1.1 header field values can be folded onto multiple lines if the | ||
869 | continuation line begins with a space or horizontal tab. All linear | ||
870 | white space, including folding, has the same semantics as SP. A | ||
871 | recipient MAY replace any linear white space with a single SP before | ||
872 | interpreting the field value or forwarding the message downstream. | ||
873 | |||
874 | LWS = [CRLF] 1*( SP | HT ) | ||
875 | |||
876 | The TEXT rule is only used for descriptive field contents and values | ||
877 | that are not intended to be interpreted by the message parser. Words | ||
878 | of *TEXT MAY contain characters from character sets other than ISO- | ||
879 | 8859-1 [22] only when encoded according to the rules of RFC 2047 | ||
880 | [14]. | ||
881 | |||
882 | TEXT = <any OCTET except CTLs, | ||
883 | but including LWS> | ||
884 | |||
885 | A CRLF is allowed in the definition of TEXT only as part of a header | ||
886 | field continuation. It is expected that the folding LWS will be | ||
887 | replaced with a single SP before interpretation of the TEXT value. | ||
888 | |||
889 | Hexadecimal numeric characters are used in several protocol elements. | ||
890 | |||
891 | HEX = "A" | "B" | "C" | "D" | "E" | "F" | ||
892 | | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT | ||
893 | |||
894 | |||
895 | |||
896 | |||
897 | |||
898 | Fielding, et al. Standards Track [Page 16] | ||
899 | |||
900 | RFC 2616 HTTP/1.1 June 1999 | ||
901 | |||
902 | |||
903 | Many HTTP/1.1 header field values consist of words separated by LWS | ||
904 | or special characters. These special characters MUST be in a quoted | ||
905 | string to be used within a parameter value (as defined in section | ||
906 | 3.6). | ||
907 | |||
908 | token = 1*<any CHAR except CTLs or separators> | ||
909 | separators = "(" | ")" | "<" | ">" | "@" | ||
910 | | "," | ";" | ":" | "\" | <"> | ||
911 | | "/" | "[" | "]" | "?" | "=" | ||
912 | | "{" | "}" | SP | HT | ||
913 | |||
914 | Comments can be included in some HTTP header fields by surrounding | ||
915 | the comment text with parentheses. Comments are only allowed in | ||
916 | fields containing "comment" as part of their field value definition. | ||
917 | In all other fields, parentheses are considered part of the field | ||
918 | value. | ||
919 | |||
920 | comment = "(" *( ctext | quoted-pair | comment ) ")" | ||
921 | ctext = <any TEXT excluding "(" and ")"> | ||
922 | |||
923 | A string of text is parsed as a single word if it is quoted using | ||
924 | double-quote marks. | ||
925 | |||
926 | quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) | ||
927 | qdtext = <any TEXT except <">> | ||
928 | |||
929 | The backslash character ("\") MAY be used as a single-character | ||
930 | quoting mechanism only within quoted-string and comment constructs. | ||
931 | |||
932 | quoted-pair = "\" CHAR | ||
933 | |||
934 | 3 Protocol Parameters | ||
935 | |||
936 | 3.1 HTTP Version | ||
937 | |||
938 | HTTP uses a "<major>.<minor>" numbering scheme to indicate versions | ||
939 | of the protocol. The protocol versioning policy is intended to allow | ||
940 | the sender to indicate the format of a message and its capacity for | ||
941 | understanding further HTTP communication, rather than the features | ||
942 | obtained via that communication. No change is made to the version | ||
943 | number for the addition of message components which do not affect | ||
944 | communication behavior or which only add to extensible field values. | ||
945 | The <minor> number is incremented when the changes made to the | ||
946 | protocol add features which do not change the general message parsing | ||
947 | algorithm, but which may add to the message semantics and imply | ||
948 | additional capabilities of the sender. The <major> number is | ||
949 | incremented when the format of a message within the protocol is | ||
950 | changed. See RFC 2145 [36] for a fuller explanation. | ||
951 | |||
952 | |||
953 | |||
954 | Fielding, et al. Standards Track [Page 17] | ||
955 | |||
956 | RFC 2616 HTTP/1.1 June 1999 | ||
957 | |||
958 | |||
959 | The version of an HTTP message is indicated by an HTTP-Version field | ||
960 | in the first line of the message. | ||
961 | |||
962 | HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT | ||
963 | |||
964 | Note that the major and minor numbers MUST be treated as separate | ||
965 | integers and that each MAY be incremented higher than a single digit. | ||
966 | Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is | ||
967 | lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and | ||
968 | MUST NOT be sent. | ||
969 | |||
970 | An application that sends a request or response message that includes | ||
971 | HTTP-Version of "HTTP/1.1" MUST be at least conditionally compliant | ||
972 | with this specification. Applications that are at least conditionally | ||
973 | compliant with this specification SHOULD use an HTTP-Version of | ||
974 | "HTTP/1.1" in their messages, and MUST do so for any message that is | ||
975 | not compatible with HTTP/1.0. For more details on when to send | ||
976 | specific HTTP-Version values, see RFC 2145 [36]. | ||
977 | |||
978 | The HTTP version of an application is the highest HTTP version for | ||
979 | which the application is at least conditionally compliant. | ||
980 | |||
981 | Proxy and gateway applications need to be careful when forwarding | ||
982 | messages in protocol versions different from that of the application. | ||
983 | Since the protocol version indicates the protocol capability of the | ||
984 | sender, a proxy/gateway MUST NOT send a message with a version | ||
985 | indicator which is greater than its actual version. If a higher | ||
986 | version request is received, the proxy/gateway MUST either downgrade | ||
987 | the request version, or respond with an error, or switch to tunnel | ||
988 | behavior. | ||
989 | |||
990 | Due to interoperability problems with HTTP/1.0 proxies discovered | ||
991 | since the publication of RFC 2068[33], caching proxies MUST, gateways | ||
992 | MAY, and tunnels MUST NOT upgrade the request to the highest version | ||
993 | they support. The proxy/gateway's response to that request MUST be in | ||
994 | the same major version as the request. | ||
995 | |||
996 | Note: Converting between versions of HTTP may involve modification | ||
997 | of header fields required or forbidden by the versions involved. | ||
998 | |||
999 | 3.2 Uniform Resource Identifiers | ||
1000 | |||
1001 | URIs have been known by many names: WWW addresses, Universal Document | ||
1002 | Identifiers, Universal Resource Identifiers [3], and finally the | ||
1003 | combination of Uniform Resource Locators (URL) [4] and Names (URN) | ||
1004 | [20]. As far as HTTP is concerned, Uniform Resource Identifiers are | ||
1005 | simply formatted strings which identify--via name, location, or any | ||
1006 | other characteristic--a resource. | ||
1007 | |||
1008 | |||
1009 | |||
1010 | Fielding, et al. Standards Track [Page 18] | ||
1011 | |||
1012 | RFC 2616 HTTP/1.1 June 1999 | ||
1013 | |||
1014 | |||
1015 | 3.2.1 General Syntax | ||
1016 | |||
1017 | URIs in HTTP can be represented in absolute form or relative to some | ||
1018 | known base URI [11], depending upon the context of their use. The two | ||
1019 | forms are differentiated by the fact that absolute URIs always begin | ||
1020 | with a scheme name followed by a colon. For definitive information on | ||
1021 | URL syntax and semantics, see "Uniform Resource Identifiers (URI): | ||
1022 | Generic Syntax and Semantics," RFC 2396 [42] (which replaces RFCs | ||
1023 | 1738 [4] and RFC 1808 [11]). This specification adopts the | ||
1024 | definitions of "URI-reference", "absoluteURI", "relativeURI", "port", | ||
1025 | "host","abs_path", "rel_path", and "authority" from that | ||
1026 | specification. | ||
1027 | |||
1028 | The HTTP protocol does not place any a priori limit on the length of | ||
1029 | a URI. Servers MUST be able to handle the URI of any resource they | ||
1030 | serve, and SHOULD be able to handle URIs of unbounded length if they | ||
1031 | provide GET-based forms that could generate such URIs. A server | ||
1032 | SHOULD return 414 (Request-URI Too Long) status if a URI is longer | ||
1033 | than the server can handle (see section 10.4.15). | ||
1034 | |||
1035 | Note: Servers ought to be cautious about depending on URI lengths | ||
1036 | above 255 bytes, because some older client or proxy | ||
1037 | implementations might not properly support these lengths. | ||
1038 | |||
1039 | 3.2.2 http URL | ||
1040 | |||
1041 | The "http" scheme is used to locate network resources via the HTTP | ||
1042 | protocol. This section defines the scheme-specific syntax and | ||
1043 | semantics for http URLs. | ||
1044 | |||
1045 | http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]] | ||
1046 | |||
1047 | If the port is empty or not given, port 80 is assumed. The semantics | ||
1048 | are that the identified resource is located at the server listening | ||
1049 | for TCP connections on that port of that host, and the Request-URI | ||
1050 | for the resource is abs_path (section 5.1.2). The use of IP addresses | ||
1051 | in URLs SHOULD be avoided whenever possible (see RFC 1900 [24]). If | ||
1052 | the abs_path is not present in the URL, it MUST be given as "/" when | ||
1053 | used as a Request-URI for a resource (section 5.1.2). If a proxy | ||
1054 | receives a host name which is not a fully qualified domain name, it | ||
1055 | MAY add its domain to the host name it received. If a proxy receives | ||
1056 | a fully qualified domain name, the proxy MUST NOT change the host | ||
1057 | name. | ||
1058 | |||
1059 | |||
1060 | |||
1061 | |||
1062 | |||
1063 | |||
1064 | |||
1065 | |||
1066 | Fielding, et al. Standards Track [Page 19] | ||
1067 | |||
1068 | RFC 2616 HTTP/1.1 June 1999 | ||
1069 | |||
1070 | |||
1071 | 3.2.3 URI Comparison | ||
1072 | |||
1073 | When comparing two URIs to decide if they match or not, a client | ||
1074 | SHOULD use a case-sensitive octet-by-octet comparison of the entire | ||
1075 | URIs, with these exceptions: | ||
1076 | |||
1077 | - A port that is empty or not given is equivalent to the default | ||
1078 | port for that URI-reference; | ||
1079 | |||
1080 | - Comparisons of host names MUST be case-insensitive; | ||
1081 | |||
1082 | - Comparisons of scheme names MUST be case-insensitive; | ||
1083 | |||
1084 | - An empty abs_path is equivalent to an abs_path of "/". | ||
1085 | |||
1086 | Characters other than those in the "reserved" and "unsafe" sets (see | ||
1087 | RFC 2396 [42]) are equivalent to their ""%" HEX HEX" encoding. | ||
1088 | |||
1089 | For example, the following three URIs are equivalent: | ||
1090 | |||
1091 | http://abc.com:80/~smith/home.html | ||
1092 | http://ABC.com/%7Esmith/home.html | ||
1093 | http://ABC.com:/%7esmith/home.html | ||
1094 | |||
1095 | 3.3 Date/Time Formats | ||
1096 | |||
1097 | 3.3.1 Full Date | ||
1098 | |||
1099 | HTTP applications have historically allowed three different formats | ||
1100 | for the representation of date/time stamps: | ||
1101 | |||
1102 | Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 | ||
1103 | Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 | ||
1104 | Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format | ||
1105 | |||
1106 | The first format is preferred as an Internet standard and represents | ||
1107 | a fixed-length subset of that defined by RFC 1123 [8] (an update to | ||
1108 | RFC 822 [9]). The second format is in common use, but is based on the | ||
1109 | obsolete RFC 850 [12] date format and lacks a four-digit year. | ||
1110 | HTTP/1.1 clients and servers that parse the date value MUST accept | ||
1111 | all three formats (for compatibility with HTTP/1.0), though they MUST | ||
1112 | only generate the RFC 1123 format for representing HTTP-date values | ||
1113 | in header fields. See section 19.3 for further information. | ||
1114 | |||
1115 | Note: Recipients of date values are encouraged to be robust in | ||
1116 | accepting date values that may have been sent by non-HTTP | ||
1117 | applications, as is sometimes the case when retrieving or posting | ||
1118 | messages via proxies/gateways to SMTP or NNTP. | ||
1119 | |||
1120 | |||
1121 | |||
1122 | Fielding, et al. Standards Track [Page 20] | ||
1123 | |||
1124 | RFC 2616 HTTP/1.1 June 1999 | ||
1125 | |||
1126 | |||
1127 | All HTTP date/time stamps MUST be represented in Greenwich Mean Time | ||
1128 | (GMT), without exception. For the purposes of HTTP, GMT is exactly | ||
1129 | equal to UTC (Coordinated Universal Time). This is indicated in the | ||
1130 | first two formats by the inclusion of "GMT" as the three-letter | ||
1131 | abbreviation for time zone, and MUST be assumed when reading the | ||
1132 | asctime format. HTTP-date is case sensitive and MUST NOT include | ||
1133 | additional LWS beyond that specifically included as SP in the | ||
1134 | grammar. | ||
1135 | |||
1136 | HTTP-date = rfc1123-date | rfc850-date | asctime-date | ||
1137 | rfc1123-date = wkday "," SP date1 SP time SP "GMT" | ||
1138 | rfc850-date = weekday "," SP date2 SP time SP "GMT" | ||
1139 | asctime-date = wkday SP date3 SP time SP 4DIGIT | ||
1140 | date1 = 2DIGIT SP month SP 4DIGIT | ||
1141 | ; day month year (e.g., 02 Jun 1982) | ||
1142 | date2 = 2DIGIT "-" month "-" 2DIGIT | ||
1143 | ; day-month-year (e.g., 02-Jun-82) | ||
1144 | date3 = month SP ( 2DIGIT | ( SP 1DIGIT )) | ||
1145 | ; month day (e.g., Jun 2) | ||
1146 | time = 2DIGIT ":" 2DIGIT ":" 2DIGIT | ||
1147 | ; 00:00:00 - 23:59:59 | ||
1148 | wkday = "Mon" | "Tue" | "Wed" | ||
1149 | | "Thu" | "Fri" | "Sat" | "Sun" | ||
1150 | weekday = "Monday" | "Tuesday" | "Wednesday" | ||
1151 | | "Thursday" | "Friday" | "Saturday" | "Sunday" | ||
1152 | month = "Jan" | "Feb" | "Mar" | "Apr" | ||
1153 | | "May" | "Jun" | "Jul" | "Aug" | ||
1154 | | "Sep" | "Oct" | "Nov" | "Dec" | ||
1155 | |||
1156 | Note: HTTP requirements for the date/time stamp format apply only | ||
1157 | to their usage within the protocol stream. Clients and servers are | ||
1158 | not required to use these formats for user presentation, request | ||
1159 | logging, etc. | ||
1160 | |||
1161 | 3.3.2 Delta Seconds | ||
1162 | |||
1163 | Some HTTP header fields allow a time value to be specified as an | ||
1164 | integer number of seconds, represented in decimal, after the time | ||
1165 | that the message was received. | ||
1166 | |||
1167 | delta-seconds = 1*DIGIT | ||
1168 | |||
1169 | 3.4 Character Sets | ||
1170 | |||
1171 | HTTP uses the same definition of the term "character set" as that | ||
1172 | described for MIME: | ||
1173 | |||
1174 | |||
1175 | |||
1176 | |||
1177 | |||
1178 | Fielding, et al. Standards Track [Page 21] | ||
1179 | |||
1180 | RFC 2616 HTTP/1.1 June 1999 | ||
1181 | |||
1182 | |||
1183 | The term "character set" is used in this document to refer to a | ||
1184 | method used with one or more tables to convert a sequence of octets | ||
1185 | into a sequence of characters. Note that unconditional conversion in | ||
1186 | the other direction is not required, in that not all characters may | ||
1187 | be available in a given character set and a character set may provide | ||
1188 | more than one sequence of octets to represent a particular character. | ||
1189 | This definition is intended to allow various kinds of character | ||
1190 | encoding, from simple single-table mappings such as US-ASCII to | ||
1191 | complex table switching methods such as those that use ISO-2022's | ||
1192 | techniques. However, the definition associated with a MIME character | ||
1193 | set name MUST fully specify the mapping to be performed from octets | ||
1194 | to characters. In particular, use of external profiling information | ||
1195 | to determine the exact mapping is not permitted. | ||
1196 | |||
1197 | Note: This use of the term "character set" is more commonly | ||
1198 | referred to as a "character encoding." However, since HTTP and | ||
1199 | MIME share the same registry, it is important that the terminology | ||
1200 | also be shared. | ||
1201 | |||
1202 | HTTP character sets are identified by case-insensitive tokens. The | ||
1203 | complete set of tokens is defined by the IANA Character Set registry | ||
1204 | [19]. | ||
1205 | |||
1206 | charset = token | ||
1207 | |||
1208 | Although HTTP allows an arbitrary token to be used as a charset | ||
1209 | value, any token that has a predefined value within the IANA | ||
1210 | Character Set registry [19] MUST represent the character set defined | ||
1211 | by that registry. Applications SHOULD limit their use of character | ||
1212 | sets to those defined by the IANA registry. | ||
1213 | |||
1214 | Implementors should be aware of IETF character set requirements [38] | ||
1215 | [41]. | ||
1216 | |||
1217 | 3.4.1 Missing Charset | ||
1218 | |||
1219 | Some HTTP/1.0 software has interpreted a Content-Type header without | ||
1220 | charset parameter incorrectly to mean "recipient should guess." | ||
1221 | Senders wishing to defeat this behavior MAY include a charset | ||
1222 | parameter even when the charset is ISO-8859-1 and SHOULD do so when | ||
1223 | it is known that it will not confuse the recipient. | ||
1224 | |||
1225 | Unfortunately, some older HTTP/1.0 clients did not deal properly with | ||
1226 | an explicit charset parameter. HTTP/1.1 recipients MUST respect the | ||
1227 | charset label provided by the sender; and those user agents that have | ||
1228 | a provision to "guess" a charset MUST use the charset from the | ||
1229 | |||
1230 | |||
1231 | |||
1232 | |||
1233 | |||
1234 | Fielding, et al. Standards Track [Page 22] | ||
1235 | |||
1236 | RFC 2616 HTTP/1.1 June 1999 | ||
1237 | |||
1238 | |||
1239 | content-type field if they support that charset, rather than the | ||
1240 | recipient's preference, when initially displaying a document. See | ||
1241 | section 3.7.1. | ||
1242 | |||
1243 | 3.5 Content Codings | ||
1244 | |||
1245 | Content coding values indicate an encoding transformation that has | ||
1246 | been or can be applied to an entity. Content codings are primarily | ||
1247 | used to allow a document to be compressed or otherwise usefully | ||
1248 | transformed without losing the identity of its underlying media type | ||
1249 | and without loss of information. Frequently, the entity is stored in | ||
1250 | coded form, transmitted directly, and only decoded by the recipient. | ||
1251 | |||
1252 | content-coding = token | ||
1253 | |||
1254 | All content-coding values are case-insensitive. HTTP/1.1 uses | ||
1255 | content-coding values in the Accept-Encoding (section 14.3) and | ||
1256 | Content-Encoding (section 14.11) header fields. Although the value | ||
1257 | describes the content-coding, what is more important is that it | ||
1258 | indicates what decoding mechanism will be required to remove the | ||
1259 | encoding. | ||
1260 | |||
1261 | The Internet Assigned Numbers Authority (IANA) acts as a registry for | ||
1262 | content-coding value tokens. Initially, the registry contains the | ||
1263 | following tokens: | ||
1264 | |||
1265 | gzip An encoding format produced by the file compression program | ||
1266 | "gzip" (GNU zip) as described in RFC 1952 [25]. This format is a | ||
1267 | Lempel-Ziv coding (LZ77) with a 32 bit CRC. | ||
1268 | |||
1269 | compress | ||
1270 | The encoding format produced by the common UNIX file compression | ||
1271 | program "compress". This format is an adaptive Lempel-Ziv-Welch | ||
1272 | coding (LZW). | ||
1273 | |||
1274 | Use of program names for the identification of encoding formats | ||
1275 | is not desirable and is discouraged for future encodings. Their | ||
1276 | use here is representative of historical practice, not good | ||
1277 | design. For compatibility with previous implementations of HTTP, | ||
1278 | applications SHOULD consider "x-gzip" and "x-compress" to be | ||
1279 | equivalent to "gzip" and "compress" respectively. | ||
1280 | |||
1281 | deflate | ||
1282 | The "zlib" format defined in RFC 1950 [31] in combination with | ||
1283 | the "deflate" compression mechanism described in RFC 1951 [29]. | ||
1284 | |||
1285 | |||
1286 | |||
1287 | |||
1288 | |||
1289 | |||
1290 | Fielding, et al. Standards Track [Page 23] | ||
1291 | |||
1292 | RFC 2616 HTTP/1.1 June 1999 | ||
1293 | |||
1294 | |||
1295 | identity | ||
1296 | The default (identity) encoding; the use of no transformation | ||
1297 | whatsoever. This content-coding is used only in the Accept- | ||
1298 | Encoding header, and SHOULD NOT be used in the Content-Encoding | ||
1299 | header. | ||
1300 | |||
1301 | New content-coding value tokens SHOULD be registered; to allow | ||
1302 | interoperability between clients and servers, specifications of the | ||
1303 | content coding algorithms needed to implement a new value SHOULD be | ||
1304 | publicly available and adequate for independent implementation, and | ||
1305 | conform to the purpose of content coding defined in this section. | ||
1306 | |||
1307 | 3.6 Transfer Codings | ||
1308 | |||
1309 | Transfer-coding values are used to indicate an encoding | ||
1310 | transformation that has been, can be, or may need to be applied to an | ||
1311 | entity-body in order to ensure "safe transport" through the network. | ||
1312 | This differs from a content coding in that the transfer-coding is a | ||
1313 | property of the message, not of the original entity. | ||
1314 | |||
1315 | transfer-coding = "chunked" | transfer-extension | ||
1316 | transfer-extension = token *( ";" parameter ) | ||
1317 | |||
1318 | Parameters are in the form of attribute/value pairs. | ||
1319 | |||
1320 | parameter = attribute "=" value | ||
1321 | attribute = token | ||
1322 | value = token | quoted-string | ||
1323 | |||
1324 | All transfer-coding values are case-insensitive. HTTP/1.1 uses | ||
1325 | transfer-coding values in the TE header field (section 14.39) and in | ||
1326 | the Transfer-Encoding header field (section 14.41). | ||
1327 | |||
1328 | Whenever a transfer-coding is applied to a message-body, the set of | ||
1329 | transfer-codings MUST include "chunked", unless the message is | ||
1330 | terminated by closing the connection. When the "chunked" transfer- | ||
1331 | coding is used, it MUST be the last transfer-coding applied to the | ||
1332 | message-body. The "chunked" transfer-coding MUST NOT be applied more | ||
1333 | than once to a message-body. These rules allow the recipient to | ||
1334 | determine the transfer-length of the message (section 4.4). | ||
1335 | |||
1336 | Transfer-codings are analogous to the Content-Transfer-Encoding | ||
1337 | values of MIME [7], which were designed to enable safe transport of | ||
1338 | binary data over a 7-bit transport service. However, safe transport | ||
1339 | has a different focus for an 8bit-clean transfer protocol. In HTTP, | ||
1340 | the only unsafe characteristic of message-bodies is the difficulty in | ||
1341 | determining the exact body length (section 7.2.2), or the desire to | ||
1342 | encrypt data over a shared transport. | ||
1343 | |||
1344 | |||
1345 | |||
1346 | Fielding, et al. Standards Track [Page 24] | ||
1347 | |||
1348 | RFC 2616 HTTP/1.1 June 1999 | ||
1349 | |||
1350 | |||
1351 | The Internet Assigned Numbers Authority (IANA) acts as a registry for | ||
1352 | transfer-coding value tokens. Initially, the registry contains the | ||
1353 | following tokens: "chunked" (section 3.6.1), "identity" (section | ||
1354 | 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate" | ||
1355 | (section 3.5). | ||
1356 | |||
1357 | New transfer-coding value tokens SHOULD be registered in the same way | ||
1358 | as new content-coding value tokens (section 3.5). | ||
1359 | |||
1360 | A server which receives an entity-body with a transfer-coding it does | ||
1361 | not understand SHOULD return 501 (Unimplemented), and close the | ||
1362 | connection. A server MUST NOT send transfer-codings to an HTTP/1.0 | ||
1363 | client. | ||
1364 | |||
1365 | 3.6.1 Chunked Transfer Coding | ||
1366 | |||
1367 | The chunked encoding modifies the body of a message in order to | ||
1368 | transfer it as a series of chunks, each with its own size indicator, | ||
1369 | followed by an OPTIONAL trailer containing entity-header fields. This | ||
1370 | allows dynamically produced content to be transferred along with the | ||
1371 | information necessary for the recipient to verify that it has | ||
1372 | received the full message. | ||
1373 | |||
1374 | Chunked-Body = *chunk | ||
1375 | last-chunk | ||
1376 | trailer | ||
1377 | CRLF | ||
1378 | |||
1379 | chunk = chunk-size [ chunk-extension ] CRLF | ||
1380 | chunk-data CRLF | ||
1381 | chunk-size = 1*HEX | ||
1382 | last-chunk = 1*("0") [ chunk-extension ] CRLF | ||
1383 | |||
1384 | chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) | ||
1385 | chunk-ext-name = token | ||
1386 | chunk-ext-val = token | quoted-string | ||
1387 | chunk-data = chunk-size(OCTET) | ||
1388 | trailer = *(entity-header CRLF) | ||
1389 | |||
1390 | The chunk-size field is a string of hex digits indicating the size of | ||
1391 | the chunk. The chunked encoding is ended by any chunk whose size is | ||
1392 | zero, followed by the trailer, which is terminated by an empty line. | ||
1393 | |||
1394 | The trailer allows the sender to include additional HTTP header | ||
1395 | fields at the end of the message. The Trailer header field can be | ||
1396 | used to indicate which header fields are included in a trailer (see | ||
1397 | section 14.40). | ||
1398 | |||
1399 | |||
1400 | |||
1401 | |||
1402 | Fielding, et al. Standards Track [Page 25] | ||
1403 | |||
1404 | RFC 2616 HTTP/1.1 June 1999 | ||
1405 | |||
1406 | |||
1407 | A server using chunked transfer-coding in a response MUST NOT use the | ||
1408 | trailer for any header fields unless at least one of the following is | ||
1409 | true: | ||
1410 | |||
1411 | a)the request included a TE header field that indicates "trailers" is | ||
1412 | acceptable in the transfer-coding of the response, as described in | ||
1413 | section 14.39; or, | ||
1414 | |||
1415 | b)the server is the origin server for the response, the trailer | ||
1416 | fields consist entirely of optional metadata, and the recipient | ||
1417 | could use the message (in a manner acceptable to the origin server) | ||
1418 | without receiving this metadata. In other words, the origin server | ||
1419 | is willing to accept the possibility that the trailer fields might | ||
1420 | be silently discarded along the path to the client. | ||
1421 | |||
1422 | This requirement prevents an interoperability failure when the | ||
1423 | message is being received by an HTTP/1.1 (or later) proxy and | ||
1424 | forwarded to an HTTP/1.0 recipient. It avoids a situation where | ||
1425 | compliance with the protocol would have necessitated a possibly | ||
1426 | infinite buffer on the proxy. | ||
1427 | |||
1428 | An example process for decoding a Chunked-Body is presented in | ||
1429 | appendix 19.4.6. | ||
1430 | |||
1431 | All HTTP/1.1 applications MUST be able to receive and decode the | ||
1432 | "chunked" transfer-coding, and MUST ignore chunk-extension extensions | ||
1433 | they do not understand. | ||
1434 | |||
1435 | 3.7 Media Types | ||
1436 | |||
1437 | HTTP uses Internet Media Types [17] in the Content-Type (section | ||
1438 | 14.17) and Accept (section 14.1) header fields in order to provide | ||
1439 | open and extensible data typing and type negotiation. | ||
1440 | |||
1441 | media-type = type "/" subtype *( ";" parameter ) | ||
1442 | type = token | ||
1443 | subtype = token | ||
1444 | |||
1445 | Parameters MAY follow the type/subtype in the form of attribute/value | ||
1446 | pairs (as defined in section 3.6). | ||
1447 | |||
1448 | The type, subtype, and parameter attribute names are case- | ||
1449 | insensitive. Parameter values might or might not be case-sensitive, | ||
1450 | depending on the semantics of the parameter name. Linear white space | ||
1451 | (LWS) MUST NOT be used between the type and subtype, nor between an | ||
1452 | attribute and its value. The presence or absence of a parameter might | ||
1453 | be significant to the processing of a media-type, depending on its | ||
1454 | definition within the media type registry. | ||
1455 | |||
1456 | |||
1457 | |||
1458 | Fielding, et al. Standards Track [Page 26] | ||
1459 | |||
1460 | RFC 2616 HTTP/1.1 June 1999 | ||
1461 | |||
1462 | |||
1463 | Note that some older HTTP applications do not recognize media type | ||
1464 | parameters. When sending data to older HTTP applications, | ||
1465 | implementations SHOULD only use media type parameters when they are | ||
1466 | required by that type/subtype definition. | ||
1467 | |||
1468 | Media-type values are registered with the Internet Assigned Number | ||
1469 | Authority (IANA [19]). The media type registration process is | ||
1470 | outlined in RFC 1590 [17]. Use of non-registered media types is | ||
1471 | discouraged. | ||
1472 | |||
1473 | 3.7.1 Canonicalization and Text Defaults | ||
1474 | |||
1475 | Internet media types are registered with a canonical form. An | ||
1476 | entity-body transferred via HTTP messages MUST be represented in the | ||
1477 | appropriate canonical form prior to its transmission except for | ||
1478 | "text" types, as defined in the next paragraph. | ||
1479 | |||
1480 | When in canonical form, media subtypes of the "text" type use CRLF as | ||
1481 | the text line break. HTTP relaxes this requirement and allows the | ||
1482 | transport of text media with plain CR or LF alone representing a line | ||
1483 | break when it is done consistently for an entire entity-body. HTTP | ||
1484 | applications MUST accept CRLF, bare CR, and bare LF as being | ||
1485 | representative of a line break in text media received via HTTP. In | ||
1486 | addition, if the text is represented in a character set that does not | ||
1487 | use octets 13 and 10 for CR and LF respectively, as is the case for | ||
1488 | some multi-byte character sets, HTTP allows the use of whatever octet | ||
1489 | sequences are defined by that character set to represent the | ||
1490 | equivalent of CR and LF for line breaks. This flexibility regarding | ||
1491 | line breaks applies only to text media in the entity-body; a bare CR | ||
1492 | or LF MUST NOT be substituted for CRLF within any of the HTTP control | ||
1493 | structures (such as header fields and multipart boundaries). | ||
1494 | |||
1495 | If an entity-body is encoded with a content-coding, the underlying | ||
1496 | data MUST be in a form defined above prior to being encoded. | ||
1497 | |||
1498 | The "charset" parameter is used with some media types to define the | ||
1499 | character set (section 3.4) of the data. When no explicit charset | ||
1500 | parameter is provided by the sender, media subtypes of the "text" | ||
1501 | type are defined to have a default charset value of "ISO-8859-1" when | ||
1502 | received via HTTP. Data in character sets other than "ISO-8859-1" or | ||
1503 | its subsets MUST be labeled with an appropriate charset value. See | ||
1504 | section 3.4.1 for compatibility problems. | ||
1505 | |||
1506 | 3.7.2 Multipart Types | ||
1507 | |||
1508 | MIME provides for a number of "multipart" types -- encapsulations of | ||
1509 | one or more entities within a single message-body. All multipart | ||
1510 | types share a common syntax, as defined in section 5.1.1 of RFC 2046 | ||
1511 | |||
1512 | |||
1513 | |||
1514 | Fielding, et al. Standards Track [Page 27] | ||
1515 | |||
1516 | RFC 2616 HTTP/1.1 June 1999 | ||
1517 | |||
1518 | |||
1519 | [40], and MUST include a boundary parameter as part of the media type | ||
1520 | value. The message body is itself a protocol element and MUST | ||
1521 | therefore use only CRLF to represent line breaks between body-parts. | ||
1522 | Unlike in RFC 2046, the epilogue of any multipart message MUST be | ||
1523 | empty; HTTP applications MUST NOT transmit the epilogue (even if the | ||
1524 | original multipart contains an epilogue). These restrictions exist in | ||
1525 | order to preserve the self-delimiting nature of a multipart message- | ||
1526 | body, wherein the "end" of the message-body is indicated by the | ||
1527 | ending multipart boundary. | ||
1528 | |||
1529 | In general, HTTP treats a multipart message-body no differently than | ||
1530 | any other media type: strictly as payload. The one exception is the | ||
1531 | "multipart/byteranges" type (appendix 19.2) when it appears in a 206 | ||
1532 | (Partial Content) response, which will be interpreted by some HTTP | ||
1533 | caching mechanisms as described in sections 13.5.4 and 14.16. In all | ||
1534 | other cases, an HTTP user agent SHOULD follow the same or similar | ||
1535 | behavior as a MIME user agent would upon receipt of a multipart type. | ||
1536 | The MIME header fields within each body-part of a multipart message- | ||
1537 | body do not have any significance to HTTP beyond that defined by | ||
1538 | their MIME semantics. | ||
1539 | |||
1540 | In general, an HTTP user agent SHOULD follow the same or similar | ||
1541 | behavior as a MIME user agent would upon receipt of a multipart type. | ||
1542 | If an application receives an unrecognized multipart subtype, the | ||
1543 | application MUST treat it as being equivalent to "multipart/mixed". | ||
1544 | |||
1545 | Note: The "multipart/form-data" type has been specifically defined | ||
1546 | for carrying form data suitable for processing via the POST | ||
1547 | request method, as described in RFC 1867 [15]. | ||
1548 | |||
1549 | 3.8 Product Tokens | ||
1550 | |||
1551 | Product tokens are used to allow communicating applications to | ||
1552 | identify themselves by software name and version. Most fields using | ||
1553 | product tokens also allow sub-products which form a significant part | ||
1554 | of the application to be listed, separated by white space. By | ||
1555 | convention, the products are listed in order of their significance | ||
1556 | for identifying the application. | ||
1557 | |||
1558 | product = token ["/" product-version] | ||
1559 | product-version = token | ||
1560 | |||
1561 | Examples: | ||
1562 | |||
1563 | User-Agent: CERN-LineMode/2.15 libwww/2.17b3 | ||
1564 | Server: Apache/0.8.4 | ||
1565 | |||
1566 | |||
1567 | |||
1568 | |||
1569 | |||
1570 | Fielding, et al. Standards Track [Page 28] | ||
1571 | |||
1572 | RFC 2616 HTTP/1.1 June 1999 | ||
1573 | |||
1574 | |||
1575 | Product tokens SHOULD be short and to the point. They MUST NOT be | ||
1576 | used for advertising or other non-essential information. Although any | ||
1577 | token character MAY appear in a product-version, this token SHOULD | ||
1578 | only be used for a version identifier (i.e., successive versions of | ||
1579 | the same product SHOULD only differ in the product-version portion of | ||
1580 | the product value). | ||
1581 | |||
1582 | 3.9 Quality Values | ||
1583 | |||
1584 | HTTP content negotiation (section 12) uses short "floating point" | ||
1585 | numbers to indicate the relative importance ("weight") of various | ||
1586 | negotiable parameters. A weight is normalized to a real number in | ||
1587 | the range 0 through 1, where 0 is the minimum and 1 the maximum | ||
1588 | value. If a parameter has a quality value of 0, then content with | ||
1589 | this parameter is `not acceptable' for the client. HTTP/1.1 | ||
1590 | applications MUST NOT generate more than three digits after the | ||
1591 | decimal point. User configuration of these values SHOULD also be | ||
1592 | limited in this fashion. | ||
1593 | |||
1594 | qvalue = ( "0" [ "." 0*3DIGIT ] ) | ||
1595 | | ( "1" [ "." 0*3("0") ] ) | ||
1596 | |||
1597 | "Quality values" is a misnomer, since these values merely represent | ||
1598 | relative degradation in desired quality. | ||
1599 | |||
1600 | 3.10 Language Tags | ||
1601 | |||
1602 | A language tag identifies a natural language spoken, written, or | ||
1603 | otherwise conveyed by human beings for communication of information | ||
1604 | to other human beings. Computer languages are explicitly excluded. | ||
1605 | HTTP uses language tags within the Accept-Language and Content- | ||
1606 | Language fields. | ||
1607 | |||
1608 | The syntax and registry of HTTP language tags is the same as that | ||
1609 | defined by RFC 1766 [1]. In summary, a language tag is composed of 1 | ||
1610 | or more parts: A primary language tag and a possibly empty series of | ||
1611 | subtags: | ||
1612 | |||
1613 | language-tag = primary-tag *( "-" subtag ) | ||
1614 | primary-tag = 1*8ALPHA | ||
1615 | subtag = 1*8ALPHA | ||
1616 | |||
1617 | White space is not allowed within the tag and all tags are case- | ||
1618 | insensitive. The name space of language tags is administered by the | ||
1619 | IANA. Example tags include: | ||
1620 | |||
1621 | en, en-US, en-cockney, i-cherokee, x-pig-latin | ||
1622 | |||
1623 | |||
1624 | |||
1625 | |||
1626 | Fielding, et al. Standards Track [Page 29] | ||
1627 | |||
1628 | RFC 2616 HTTP/1.1 June 1999 | ||
1629 | |||
1630 | |||
1631 | where any two-letter primary-tag is an ISO-639 language abbreviation | ||
1632 | and any two-letter initial subtag is an ISO-3166 country code. (The | ||
1633 | last three tags above are not registered tags; all but the last are | ||
1634 | examples of tags which could be registered in future.) | ||
1635 | |||
1636 | 3.11 Entity Tags | ||
1637 | |||
1638 | Entity tags are used for comparing two or more entities from the same | ||
1639 | requested resource. HTTP/1.1 uses entity tags in the ETag (section | ||
1640 | 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and | ||
1641 | If-Range (section 14.27) header fields. The definition of how they | ||
1642 | are used and compared as cache validators is in section 13.3.3. An | ||
1643 | entity tag consists of an opaque quoted string, possibly prefixed by | ||
1644 | a weakness indicator. | ||
1645 | |||
1646 | entity-tag = [ weak ] opaque-tag | ||
1647 | weak = "W/" | ||
1648 | opaque-tag = quoted-string | ||
1649 | |||
1650 | A "strong entity tag" MAY be shared by two entities of a resource | ||
1651 | only if they are equivalent by octet equality. | ||
1652 | |||
1653 | A "weak entity tag," indicated by the "W/" prefix, MAY be shared by | ||
1654 | two entities of a resource only if the entities are equivalent and | ||
1655 | could be substituted for each other with no significant change in | ||
1656 | semantics. A weak entity tag can only be used for weak comparison. | ||
1657 | |||
1658 | An entity tag MUST be unique across all versions of all entities | ||
1659 | associated with a particular resource. A given entity tag value MAY | ||
1660 | be used for entities obtained by requests on different URIs. The use | ||
1661 | of the same entity tag value in conjunction with entities obtained by | ||
1662 | requests on different URIs does not imply the equivalence of those | ||
1663 | entities. | ||
1664 | |||
1665 | 3.12 Range Units | ||
1666 | |||
1667 | HTTP/1.1 allows a client to request that only part (a range of) the | ||
1668 | response entity be included within the response. HTTP/1.1 uses range | ||
1669 | units in the Range (section 14.35) and Content-Range (section 14.16) | ||
1670 | header fields. An entity can be broken down into subranges according | ||
1671 | to various structural units. | ||
1672 | |||
1673 | range-unit = bytes-unit | other-range-unit | ||
1674 | bytes-unit = "bytes" | ||
1675 | other-range-unit = token | ||
1676 | |||
1677 | The only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 | ||
1678 | implementations MAY ignore ranges specified using other units. | ||
1679 | |||
1680 | |||
1681 | |||
1682 | Fielding, et al. Standards Track [Page 30] | ||
1683 | |||
1684 | RFC 2616 HTTP/1.1 June 1999 | ||
1685 | |||
1686 | |||
1687 | HTTP/1.1 has been designed to allow implementations of applications | ||
1688 | that do not depend on knowledge of ranges. | ||
1689 | |||
1690 | 4 HTTP Message | ||
1691 | |||
1692 | 4.1 Message Types | ||
1693 | |||
1694 | HTTP messages consist of requests from client to server and responses | ||
1695 | from server to client. | ||
1696 | |||
1697 | HTTP-message = Request | Response ; HTTP/1.1 messages | ||
1698 | |||
1699 | Request (section 5) and Response (section 6) messages use the generic | ||
1700 | message format of RFC 822 [9] for transferring entities (the payload | ||
1701 | of the message). Both types of message consist of a start-line, zero | ||
1702 | or more header fields (also known as "headers"), an empty line (i.e., | ||
1703 | a line with nothing preceding the CRLF) indicating the end of the | ||
1704 | header fields, and possibly a message-body. | ||
1705 | |||
1706 | generic-message = start-line | ||
1707 | *(message-header CRLF) | ||
1708 | CRLF | ||
1709 | [ message-body ] | ||
1710 | start-line = Request-Line | Status-Line | ||
1711 | |||
1712 | In the interest of robustness, servers SHOULD ignore any empty | ||
1713 | line(s) received where a Request-Line is expected. In other words, if | ||
1714 | the server is reading the protocol stream at the beginning of a | ||
1715 | message and receives a CRLF first, it should ignore the CRLF. | ||
1716 | |||
1717 | Certain buggy HTTP/1.0 client implementations generate extra CRLF's | ||
1718 | after a POST request. To restate what is explicitly forbidden by the | ||
1719 | BNF, an HTTP/1.1 client MUST NOT preface or follow a request with an | ||
1720 | extra CRLF. | ||
1721 | |||
1722 | 4.2 Message Headers | ||
1723 | |||
1724 | HTTP header fields, which include general-header (section 4.5), | ||
1725 | request-header (section 5.3), response-header (section 6.2), and | ||
1726 | entity-header (section 7.1) fields, follow the same generic format as | ||
1727 | that given in Section 3.1 of RFC 822 [9]. Each header field consists | ||
1728 | of a name followed by a colon (":") and the field value. Field names | ||
1729 | are case-insensitive. The field value MAY be preceded by any amount | ||
1730 | of LWS, though a single SP is preferred. Header fields can be | ||
1731 | extended over multiple lines by preceding each extra line with at | ||
1732 | least one SP or HT. Applications ought to follow "common form", where | ||
1733 | one is known or indicated, when generating HTTP constructs, since | ||
1734 | there might exist some implementations that fail to accept anything | ||
1735 | |||
1736 | |||
1737 | |||
1738 | Fielding, et al. Standards Track [Page 31] | ||
1739 | |||
1740 | RFC 2616 HTTP/1.1 June 1999 | ||
1741 | |||
1742 | |||
1743 | beyond the common forms. | ||
1744 | |||
1745 | message-header = field-name ":" [ field-value ] | ||
1746 | field-name = token | ||
1747 | field-value = *( field-content | LWS ) | ||
1748 | field-content = <the OCTETs making up the field-value | ||
1749 | and consisting of either *TEXT or combinations | ||
1750 | of token, separators, and quoted-string> | ||
1751 | |||
1752 | The field-content does not include any leading or trailing LWS: | ||
1753 | linear white space occurring before the first non-whitespace | ||
1754 | character of the field-value or after the last non-whitespace | ||
1755 | character of the field-value. Such leading or trailing LWS MAY be | ||
1756 | removed without changing the semantics of the field value. Any LWS | ||
1757 | that occurs between field-content MAY be replaced with a single SP | ||
1758 | before interpreting the field value or forwarding the message | ||
1759 | downstream. | ||
1760 | |||
1761 | The order in which header fields with differing field names are | ||
1762 | received is not significant. However, it is "good practice" to send | ||
1763 | general-header fields first, followed by request-header or response- | ||
1764 | header fields, and ending with the entity-header fields. | ||
1765 | |||
1766 | Multiple message-header fields with the same field-name MAY be | ||
1767 | present in a message if and only if the entire field-value for that | ||
1768 | header field is defined as a comma-separated list [i.e., #(values)]. | ||
1769 | It MUST be possible to combine the multiple header fields into one | ||
1770 | "field-name: field-value" pair, without changing the semantics of the | ||
1771 | message, by appending each subsequent field-value to the first, each | ||
1772 | separated by a comma. The order in which header fields with the same | ||
1773 | field-name are received is therefore significant to the | ||
1774 | interpretation of the combined field value, and thus a proxy MUST NOT | ||
1775 | change the order of these field values when a message is forwarded. | ||
1776 | |||
1777 | 4.3 Message Body | ||
1778 | |||
1779 | The message-body (if any) of an HTTP message is used to carry the | ||
1780 | entity-body associated with the request or response. The message-body | ||
1781 | differs from the entity-body only when a transfer-coding has been | ||
1782 | applied, as indicated by the Transfer-Encoding header field (section | ||
1783 | 14.41). | ||
1784 | |||
1785 | message-body = entity-body | ||
1786 | | <entity-body encoded as per Transfer-Encoding> | ||
1787 | |||
1788 | Transfer-Encoding MUST be used to indicate any transfer-codings | ||
1789 | applied by an application to ensure safe and proper transfer of the | ||
1790 | message. Transfer-Encoding is a property of the message, not of the | ||
1791 | |||
1792 | |||
1793 | |||
1794 | Fielding, et al. Standards Track [Page 32] | ||
1795 | |||
1796 | RFC 2616 HTTP/1.1 June 1999 | ||
1797 | |||
1798 | |||
1799 | entity, and thus MAY be added or removed by any application along the | ||
1800 | request/response chain. (However, section 3.6 places restrictions on | ||
1801 | when certain transfer-codings may be used.) | ||
1802 | |||
1803 | The rules for when a message-body is allowed in a message differ for | ||
1804 | requests and responses. | ||
1805 | |||
1806 | The presence of a message-body in a request is signaled by the | ||
1807 | inclusion of a Content-Length or Transfer-Encoding header field in | ||
1808 | the request's message-headers. A message-body MUST NOT be included in | ||
1809 | a request if the specification of the request method (section 5.1.1) | ||
1810 | does not allow sending an entity-body in requests. A server SHOULD | ||
1811 | read and forward a message-body on any request; if the request method | ||
1812 | does not include defined semantics for an entity-body, then the | ||
1813 | message-body SHOULD be ignored when handling the request. | ||
1814 | |||
1815 | For response messages, whether or not a message-body is included with | ||
1816 | a message is dependent on both the request method and the response | ||
1817 | status code (section 6.1.1). All responses to the HEAD request method | ||
1818 | MUST NOT include a message-body, even though the presence of entity- | ||
1819 | header fields might lead one to believe they do. All 1xx | ||
1820 | (informational), 204 (no content), and 304 (not modified) responses | ||
1821 | MUST NOT include a message-body. All other responses do include a | ||
1822 | message-body, although it MAY be of zero length. | ||
1823 | |||
1824 | 4.4 Message Length | ||
1825 | |||
1826 | The transfer-length of a message is the length of the message-body as | ||
1827 | it appears in the message; that is, after any transfer-codings have | ||
1828 | been applied. When a message-body is included with a message, the | ||
1829 | transfer-length of that body is determined by one of the following | ||
1830 | (in order of precedence): | ||
1831 | |||
1832 | 1.Any response message which "MUST NOT" include a message-body (such | ||
1833 | as the 1xx, 204, and 304 responses and any response to a HEAD | ||
1834 | request) is always terminated by the first empty line after the | ||
1835 | header fields, regardless of the entity-header fields present in | ||
1836 | the message. | ||
1837 | |||
1838 | 2.If a Transfer-Encoding header field (section 14.41) is present and | ||
1839 | has any value other than "identity", then the transfer-length is | ||
1840 | defined by use of the "chunked" transfer-coding (section 3.6), | ||
1841 | unless the message is terminated by closing the connection. | ||
1842 | |||
1843 | 3.If a Content-Length header field (section 14.13) is present, its | ||
1844 | decimal value in OCTETs represents both the entity-length and the | ||
1845 | transfer-length. The Content-Length header field MUST NOT be sent | ||
1846 | if these two lengths are different (i.e., if a Transfer-Encoding | ||
1847 | |||
1848 | |||
1849 | |||
1850 | Fielding, et al. Standards Track [Page 33] | ||
1851 | |||
1852 | RFC 2616 HTTP/1.1 June 1999 | ||
1853 | |||
1854 | |||
1855 | header field is present). If a message is received with both a | ||
1856 | Transfer-Encoding header field and a Content-Length header field, | ||
1857 | the latter MUST be ignored. | ||
1858 | |||
1859 | 4.If the message uses the media type "multipart/byteranges", and the | ||
1860 | ransfer-length is not otherwise specified, then this self- | ||
1861 | elimiting media type defines the transfer-length. This media type | ||
1862 | UST NOT be used unless the sender knows that the recipient can arse | ||
1863 | it; the presence in a request of a Range header with ultiple byte- | ||
1864 | range specifiers from a 1.1 client implies that the lient can parse | ||
1865 | multipart/byteranges responses. | ||
1866 | |||
1867 | A range header might be forwarded by a 1.0 proxy that does not | ||
1868 | understand multipart/byteranges; in this case the server MUST | ||
1869 | delimit the message using methods defined in items 1,3 or 5 of | ||
1870 | this section. | ||
1871 | |||
1872 | 5.By the server closing the connection. (Closing the connection | ||
1873 | cannot be used to indicate the end of a request body, since that | ||
1874 | would leave no possibility for the server to send back a response.) | ||
1875 | |||
1876 | For compatibility with HTTP/1.0 applications, HTTP/1.1 requests | ||
1877 | containing a message-body MUST include a valid Content-Length header | ||
1878 | field unless the server is known to be HTTP/1.1 compliant. If a | ||
1879 | request contains a message-body and a Content-Length is not given, | ||
1880 | the server SHOULD respond with 400 (bad request) if it cannot | ||
1881 | determine the length of the message, or with 411 (length required) if | ||
1882 | it wishes to insist on receiving a valid Content-Length. | ||
1883 | |||
1884 | All HTTP/1.1 applications that receive entities MUST accept the | ||
1885 | "chunked" transfer-coding (section 3.6), thus allowing this mechanism | ||
1886 | to be used for messages when the message length cannot be determined | ||
1887 | in advance. | ||
1888 | |||
1889 | Messages MUST NOT include both a Content-Length header field and a | ||
1890 | non-identity transfer-coding. If the message does include a non- | ||
1891 | identity transfer-coding, the Content-Length MUST be ignored. | ||
1892 | |||
1893 | When a Content-Length is given in a message where a message-body is | ||
1894 | allowed, its field value MUST exactly match the number of OCTETs in | ||
1895 | the message-body. HTTP/1.1 user agents MUST notify the user when an | ||
1896 | invalid length is received and detected. | ||
1897 | |||
1898 | 4.5 General Header Fields | ||
1899 | |||
1900 | There are a few header fields which have general applicability for | ||
1901 | both request and response messages, but which do not apply to the | ||
1902 | entity being transferred. These header fields apply only to the | ||
1903 | |||
1904 | |||
1905 | |||
1906 | Fielding, et al. Standards Track [Page 34] | ||
1907 | |||
1908 | RFC 2616 HTTP/1.1 June 1999 | ||
1909 | |||
1910 | |||
1911 | message being transmitted. | ||
1912 | |||
1913 | general-header = Cache-Control ; Section 14.9 | ||
1914 | | Connection ; Section 14.10 | ||
1915 | | Date ; Section 14.18 | ||
1916 | | Pragma ; Section 14.32 | ||
1917 | | Trailer ; Section 14.40 | ||
1918 | | Transfer-Encoding ; Section 14.41 | ||
1919 | | Upgrade ; Section 14.42 | ||
1920 | | Via ; Section 14.45 | ||
1921 | | Warning ; Section 14.46 | ||
1922 | |||
1923 | General-header field names can be extended reliably only in | ||
1924 | combination with a change in the protocol version. However, new or | ||
1925 | experimental header fields may be given the semantics of general | ||
1926 | header fields if all parties in the communication recognize them to | ||
1927 | be general-header fields. Unrecognized header fields are treated as | ||
1928 | entity-header fields. | ||
1929 | |||
1930 | 5 Request | ||
1931 | |||
1932 | A request message from a client to a server includes, within the | ||
1933 | first line of that message, the method to be applied to the resource, | ||
1934 | the identifier of the resource, and the protocol version in use. | ||
1935 | |||
1936 | Request = Request-Line ; Section 5.1 | ||
1937 | *(( general-header ; Section 4.5 | ||
1938 | | request-header ; Section 5.3 | ||
1939 | | entity-header ) CRLF) ; Section 7.1 | ||
1940 | CRLF | ||
1941 | [ message-body ] ; Section 4.3 | ||
1942 | |||
1943 | 5.1 Request-Line | ||
1944 | |||
1945 | The Request-Line begins with a method token, followed by the | ||
1946 | Request-URI and the protocol version, and ending with CRLF. The | ||
1947 | elements are separated by SP characters. No CR or LF is allowed | ||
1948 | except in the final CRLF sequence. | ||
1949 | |||
1950 | Request-Line = Method SP Request-URI SP HTTP-Version CRLF | ||
1951 | |||
1952 | |||
1953 | |||
1954 | |||
1955 | |||
1956 | |||
1957 | |||
1958 | |||
1959 | |||
1960 | |||
1961 | |||
1962 | Fielding, et al. Standards Track [Page 35] | ||
1963 | |||
1964 | RFC 2616 HTTP/1.1 June 1999 | ||
1965 | |||
1966 | |||
1967 | 5.1.1 Method | ||
1968 | |||
1969 | The Method token indicates the method to be performed on the | ||
1970 | resource identified by the Request-URI. The method is case-sensitive. | ||
1971 | |||
1972 | Method = "OPTIONS" ; Section 9.2 | ||
1973 | | "GET" ; Section 9.3 | ||
1974 | | "HEAD" ; Section 9.4 | ||
1975 | | "POST" ; Section 9.5 | ||
1976 | | "PUT" ; Section 9.6 | ||
1977 | | "DELETE" ; Section 9.7 | ||
1978 | | "TRACE" ; Section 9.8 | ||
1979 | | "CONNECT" ; Section 9.9 | ||
1980 | | extension-method | ||
1981 | extension-method = token | ||
1982 | |||
1983 | The list of methods allowed by a resource can be specified in an | ||
1984 | Allow header field (section 14.7). The return code of the response | ||
1985 | always notifies the client whether a method is currently allowed on a | ||
1986 | resource, since the set of allowed methods can change dynamically. An | ||
1987 | origin server SHOULD return the status code 405 (Method Not Allowed) | ||
1988 | if the method is known by the origin server but not allowed for the | ||
1989 | requested resource, and 501 (Not Implemented) if the method is | ||
1990 | unrecognized or not implemented by the origin server. The methods GET | ||
1991 | and HEAD MUST be supported by all general-purpose servers. All other | ||
1992 | methods are OPTIONAL; however, if the above methods are implemented, | ||
1993 | they MUST be implemented with the same semantics as those specified | ||
1994 | in section 9. | ||
1995 | |||
1996 | 5.1.2 Request-URI | ||
1997 | |||
1998 | The Request-URI is a Uniform Resource Identifier (section 3.2) and | ||
1999 | identifies the resource upon which to apply the request. | ||
2000 | |||
2001 | Request-URI = "*" | absoluteURI | abs_path | authority | ||
2002 | |||
2003 | The four options for Request-URI are dependent on the nature of the | ||
2004 | request. The asterisk "*" means that the request does not apply to a | ||
2005 | particular resource, but to the server itself, and is only allowed | ||
2006 | when the method used does not necessarily apply to a resource. One | ||
2007 | example would be | ||
2008 | |||
2009 | OPTIONS * HTTP/1.1 | ||
2010 | |||
2011 | The absoluteURI form is REQUIRED when the request is being made to a | ||
2012 | proxy. The proxy is requested to forward the request or service it | ||
2013 | from a valid cache, and return the response. Note that the proxy MAY | ||
2014 | forward the request on to another proxy or directly to the server | ||
2015 | |||
2016 | |||
2017 | |||
2018 | Fielding, et al. Standards Track [Page 36] | ||
2019 | |||
2020 | RFC 2616 HTTP/1.1 June 1999 | ||
2021 | |||
2022 | |||
2023 | specified by the absoluteURI. In order to avoid request loops, a | ||
2024 | proxy MUST be able to recognize all of its server names, including | ||
2025 | any aliases, local variations, and the numeric IP address. An example | ||
2026 | Request-Line would be: | ||
2027 | |||
2028 | GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1 | ||
2029 | |||
2030 | To allow for transition to absoluteURIs in all requests in future | ||
2031 | versions of HTTP, all HTTP/1.1 servers MUST accept the absoluteURI | ||
2032 | form in requests, even though HTTP/1.1 clients will only generate | ||
2033 | them in requests to proxies. | ||
2034 | |||
2035 | The authority form is only used by the CONNECT method (section 9.9). | ||
2036 | |||
2037 | The most common form of Request-URI is that used to identify a | ||
2038 | resource on an origin server or gateway. In this case the absolute | ||
2039 | path of the URI MUST be transmitted (see section 3.2.1, abs_path) as | ||
2040 | the Request-URI, and the network location of the URI (authority) MUST | ||
2041 | be transmitted in a Host header field. For example, a client wishing | ||
2042 | to retrieve the resource above directly from the origin server would | ||
2043 | create a TCP connection to port 80 of the host "www.w3.org" and send | ||
2044 | the lines: | ||
2045 | |||
2046 | GET /pub/WWW/TheProject.html HTTP/1.1 | ||
2047 | Host: www.w3.org | ||
2048 | |||
2049 | followed by the remainder of the Request. Note that the absolute path | ||
2050 | cannot be empty; if none is present in the original URI, it MUST be | ||
2051 | given as "/" (the server root). | ||
2052 | |||
2053 | The Request-URI is transmitted in the format specified in section | ||
2054 | 3.2.1. If the Request-URI is encoded using the "% HEX HEX" encoding | ||
2055 | [42], the origin server MUST decode the Request-URI in order to | ||
2056 | properly interpret the request. Servers SHOULD respond to invalid | ||
2057 | Request-URIs with an appropriate status code. | ||
2058 | |||
2059 | A transparent proxy MUST NOT rewrite the "abs_path" part of the | ||
2060 | received Request-URI when forwarding it to the next inbound server, | ||
2061 | except as noted above to replace a null abs_path with "/". | ||
2062 | |||
2063 | Note: The "no rewrite" rule prevents the proxy from changing the | ||
2064 | meaning of the request when the origin server is improperly using | ||
2065 | a non-reserved URI character for a reserved purpose. Implementors | ||
2066 | should be aware that some pre-HTTP/1.1 proxies have been known to | ||
2067 | rewrite the Request-URI. | ||
2068 | |||
2069 | |||
2070 | |||
2071 | |||
2072 | |||
2073 | |||
2074 | Fielding, et al. Standards Track [Page 37] | ||
2075 | |||
2076 | RFC 2616 HTTP/1.1 June 1999 | ||
2077 | |||
2078 | |||
2079 | 5.2 The Resource Identified by a Request | ||
2080 | |||
2081 | The exact resource identified by an Internet request is determined by | ||
2082 | examining both the Request-URI and the Host header field. | ||
2083 | |||
2084 | An origin server that does not allow resources to differ by the | ||
2085 | requested host MAY ignore the Host header field value when | ||
2086 | determining the resource identified by an HTTP/1.1 request. (But see | ||
2087 | section 19.6.1.1 for other requirements on Host support in HTTP/1.1.) | ||
2088 | |||
2089 | An origin server that does differentiate resources based on the host | ||
2090 | requested (sometimes referred to as virtual hosts or vanity host | ||
2091 | names) MUST use the following rules for determining the requested | ||
2092 | resource on an HTTP/1.1 request: | ||
2093 | |||
2094 | 1. If Request-URI is an absoluteURI, the host is part of the | ||
2095 | Request-URI. Any Host header field value in the request MUST be | ||
2096 | ignored. | ||
2097 | |||
2098 | 2. If the Request-URI is not an absoluteURI, and the request includes | ||
2099 | a Host header field, the host is determined by the Host header | ||
2100 | field value. | ||
2101 | |||
2102 | 3. If the host as determined by rule 1 or 2 is not a valid host on | ||
2103 | the server, the response MUST be a 400 (Bad Request) error message. | ||
2104 | |||
2105 | Recipients of an HTTP/1.0 request that lacks a Host header field MAY | ||
2106 | attempt to use heuristics (e.g., examination of the URI path for | ||
2107 | something unique to a particular host) in order to determine what | ||
2108 | exact resource is being requested. | ||
2109 | |||
2110 | 5.3 Request Header Fields | ||
2111 | |||
2112 | The request-header fields allow the client to pass additional | ||
2113 | information about the request, and about the client itself, to the | ||
2114 | server. These fields act as request modifiers, with semantics | ||
2115 | equivalent to the parameters on a programming language method | ||
2116 | invocation. | ||
2117 | |||
2118 | request-header = Accept ; Section 14.1 | ||
2119 | | Accept-Charset ; Section 14.2 | ||
2120 | | Accept-Encoding ; Section 14.3 | ||
2121 | | Accept-Language ; Section 14.4 | ||
2122 | | Authorization ; Section 14.8 | ||
2123 | | Expect ; Section 14.20 | ||
2124 | | From ; Section 14.22 | ||
2125 | | Host ; Section 14.23 | ||
2126 | | If-Match ; Section 14.24 | ||
2127 | |||
2128 | |||
2129 | |||
2130 | Fielding, et al. Standards Track [Page 38] | ||
2131 | |||
2132 | RFC 2616 HTTP/1.1 June 1999 | ||
2133 | |||
2134 | |||
2135 | | If-Modified-Since ; Section 14.25 | ||
2136 | | If-None-Match ; Section 14.26 | ||
2137 | | If-Range ; Section 14.27 | ||
2138 | | If-Unmodified-Since ; Section 14.28 | ||
2139 | | Max-Forwards ; Section 14.31 | ||
2140 | | Proxy-Authorization ; Section 14.34 | ||
2141 | | Range ; Section 14.35 | ||
2142 | | Referer ; Section 14.36 | ||
2143 | | TE ; Section 14.39 | ||
2144 | | User-Agent ; Section 14.43 | ||
2145 | |||
2146 | Request-header field names can be extended reliably only in | ||
2147 | combination with a change in the protocol version. However, new or | ||
2148 | experimental header fields MAY be given the semantics of request- | ||
2149 | header fields if all parties in the communication recognize them to | ||
2150 | be request-header fields. Unrecognized header fields are treated as | ||
2151 | entity-header fields. | ||
2152 | |||
2153 | 6 Response | ||
2154 | |||
2155 | After receiving and interpreting a request message, a server responds | ||
2156 | with an HTTP response message. | ||
2157 | |||
2158 | Response = Status-Line ; Section 6.1 | ||
2159 | *(( general-header ; Section 4.5 | ||
2160 | | response-header ; Section 6.2 | ||
2161 | | entity-header ) CRLF) ; Section 7.1 | ||
2162 | CRLF | ||
2163 | [ message-body ] ; Section 7.2 | ||
2164 | |||
2165 | 6.1 Status-Line | ||
2166 | |||
2167 | The first line of a Response message is the Status-Line, consisting | ||
2168 | of the protocol version followed by a numeric status code and its | ||
2169 | associated textual phrase, with each element separated by SP | ||
2170 | characters. No CR or LF is allowed except in the final CRLF sequence. | ||
2171 | |||
2172 | Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF | ||
2173 | |||
2174 | 6.1.1 Status Code and Reason Phrase | ||
2175 | |||
2176 | The Status-Code element is a 3-digit integer result code of the | ||
2177 | attempt to understand and satisfy the request. These codes are fully | ||
2178 | defined in section 10. The Reason-Phrase is intended to give a short | ||
2179 | textual description of the Status-Code. The Status-Code is intended | ||
2180 | for use by automata and the Reason-Phrase is intended for the human | ||
2181 | user. The client is not required to examine or display the Reason- | ||
2182 | Phrase. | ||
2183 | |||
2184 | |||
2185 | |||
2186 | Fielding, et al. Standards Track [Page 39] | ||
2187 | |||
2188 | RFC 2616 HTTP/1.1 June 1999 | ||
2189 | |||
2190 | |||
2191 | The first digit of the Status-Code defines the class of response. The | ||
2192 | last two digits do not have any categorization role. There are 5 | ||
2193 | values for the first digit: | ||
2194 | |||
2195 | - 1xx: Informational - Request received, continuing process | ||
2196 | |||
2197 | - 2xx: Success - The action was successfully received, | ||
2198 | understood, and accepted | ||
2199 | |||
2200 | - 3xx: Redirection - Further action must be taken in order to | ||
2201 | complete the request | ||
2202 | |||
2203 | - 4xx: Client Error - The request contains bad syntax or cannot | ||
2204 | be fulfilled | ||
2205 | |||
2206 | - 5xx: Server Error - The server failed to fulfill an apparently | ||
2207 | valid request | ||
2208 | |||
2209 | The individual values of the numeric status codes defined for | ||
2210 | HTTP/1.1, and an example set of corresponding Reason-Phrase's, are | ||
2211 | presented below. The reason phrases listed here are only | ||
2212 | recommendations -- they MAY be replaced by local equivalents without | ||
2213 | affecting the protocol. | ||
2214 | |||
2215 | Status-Code = | ||
2216 | "100" ; Section 10.1.1: Continue | ||
2217 | | "101" ; Section 10.1.2: Switching Protocols | ||
2218 | | "200" ; Section 10.2.1: OK | ||
2219 | | "201" ; Section 10.2.2: Created | ||
2220 | | "202" ; Section 10.2.3: Accepted | ||
2221 | | "203" ; Section 10.2.4: Non-Authoritative Information | ||
2222 | | "204" ; Section 10.2.5: No Content | ||
2223 | | "205" ; Section 10.2.6: Reset Content | ||
2224 | | "206" ; Section 10.2.7: Partial Content | ||
2225 | | "300" ; Section 10.3.1: Multiple Choices | ||
2226 | | "301" ; Section 10.3.2: Moved Permanently | ||
2227 | | "302" ; Section 10.3.3: Found | ||
2228 | | "303" ; Section 10.3.4: See Other | ||
2229 | | "304" ; Section 10.3.5: Not Modified | ||
2230 | | "305" ; Section 10.3.6: Use Proxy | ||
2231 | | "307" ; Section 10.3.8: Temporary Redirect | ||
2232 | | "400" ; Section 10.4.1: Bad Request | ||
2233 | | "401" ; Section 10.4.2: Unauthorized | ||
2234 | | "402" ; Section 10.4.3: Payment Required | ||
2235 | | "403" ; Section 10.4.4: Forbidden | ||
2236 | | "404" ; Section 10.4.5: Not Found | ||
2237 | | "405" ; Section 10.4.6: Method Not Allowed | ||
2238 | | "406" ; Section 10.4.7: Not Acceptable | ||
2239 | |||
2240 | |||
2241 | |||
2242 | Fielding, et al. Standards Track [Page 40] | ||
2243 | |||
2244 | RFC 2616 HTTP/1.1 June 1999 | ||
2245 | |||
2246 | |||
2247 | | "407" ; Section 10.4.8: Proxy Authentication Required | ||
2248 | | "408" ; Section 10.4.9: Request Time-out | ||
2249 | | "409" ; Section 10.4.10: Conflict | ||
2250 | | "410" ; Section 10.4.11: Gone | ||
2251 | | "411" ; Section 10.4.12: Length Required | ||
2252 | | "412" ; Section 10.4.13: Precondition Failed | ||
2253 | | "413" ; Section 10.4.14: Request Entity Too Large | ||
2254 | | "414" ; Section 10.4.15: Request-URI Too Large | ||
2255 | | "415" ; Section 10.4.16: Unsupported Media Type | ||
2256 | | "416" ; Section 10.4.17: Requested range not satisfiable | ||
2257 | | "417" ; Section 10.4.18: Expectation Failed | ||
2258 | | "500" ; Section 10.5.1: Internal Server Error | ||
2259 | | "501" ; Section 10.5.2: Not Implemented | ||
2260 | | "502" ; Section 10.5.3: Bad Gateway | ||
2261 | | "503" ; Section 10.5.4: Service Unavailable | ||
2262 | | "504" ; Section 10.5.5: Gateway Time-out | ||
2263 | | "505" ; Section 10.5.6: HTTP Version not supported | ||
2264 | | extension-code | ||
2265 | |||
2266 | extension-code = 3DIGIT | ||
2267 | Reason-Phrase = *<TEXT, excluding CR, LF> | ||
2268 | |||
2269 | HTTP status codes are extensible. HTTP applications are not required | ||
2270 | to understand the meaning of all registered status codes, though such | ||
2271 | understanding is obviously desirable. However, applications MUST | ||
2272 | understand the class of any status code, as indicated by the first | ||
2273 | digit, and treat any unrecognized response as being equivalent to the | ||
2274 | x00 status code of that class, with the exception that an | ||
2275 | unrecognized response MUST NOT be cached. For example, if an | ||
2276 | unrecognized status code of 431 is received by the client, it can | ||
2277 | safely assume that there was something wrong with its request and | ||
2278 | treat the response as if it had received a 400 status code. In such | ||
2279 | cases, user agents SHOULD present to the user the entity returned | ||
2280 | with the response, since that entity is likely to include human- | ||
2281 | readable information which will explain the unusual status. | ||
2282 | |||
2283 | 6.2 Response Header Fields | ||
2284 | |||
2285 | The response-header fields allow the server to pass additional | ||
2286 | information about the response which cannot be placed in the Status- | ||
2287 | Line. These header fields give information about the server and about | ||
2288 | further access to the resource identified by the Request-URI. | ||
2289 | |||
2290 | response-header = Accept-Ranges ; Section 14.5 | ||
2291 | | Age ; Section 14.6 | ||
2292 | | ETag ; Section 14.19 | ||
2293 | | Location ; Section 14.30 | ||
2294 | | Proxy-Authenticate ; Section 14.33 | ||
2295 | |||
2296 | |||
2297 | |||
2298 | Fielding, et al. Standards Track [Page 41] | ||
2299 | |||
2300 | RFC 2616 HTTP/1.1 June 1999 | ||
2301 | |||
2302 | |||
2303 | | Retry-After ; Section 14.37 | ||
2304 | | Server ; Section 14.38 | ||
2305 | | Vary ; Section 14.44 | ||
2306 | | WWW-Authenticate ; Section 14.47 | ||
2307 | |||
2308 | Response-header field names can be extended reliably only in | ||
2309 | combination with a change in the protocol version. However, new or | ||
2310 | experimental header fields MAY be given the semantics of response- | ||
2311 | header fields if all parties in the communication recognize them to | ||
2312 | be response-header fields. Unrecognized header fields are treated as | ||
2313 | entity-header fields. | ||
2314 | |||
2315 | 7 Entity | ||
2316 | |||
2317 | Request and Response messages MAY transfer an entity if not otherwise | ||
2318 | restricted by the request method or response status code. An entity | ||
2319 | consists of entity-header fields and an entity-body, although some | ||
2320 | responses will only include the entity-headers. | ||
2321 | |||
2322 | In this section, both sender and recipient refer to either the client | ||
2323 | or the server, depending on who sends and who receives the entity. | ||
2324 | |||
2325 | 7.1 Entity Header Fields | ||
2326 | |||
2327 | Entity-header fields define metainformation about the entity-body or, | ||
2328 | if no body is present, about the resource identified by the request. | ||
2329 | Some of this metainformation is OPTIONAL; some might be REQUIRED by | ||
2330 | portions of this specification. | ||
2331 | |||
2332 | entity-header = Allow ; Section 14.7 | ||
2333 | | Content-Encoding ; Section 14.11 | ||
2334 | | Content-Language ; Section 14.12 | ||
2335 | | Content-Length ; Section 14.13 | ||
2336 | | Content-Location ; Section 14.14 | ||
2337 | | Content-MD5 ; Section 14.15 | ||
2338 | | Content-Range ; Section 14.16 | ||
2339 | | Content-Type ; Section 14.17 | ||
2340 | | Expires ; Section 14.21 | ||
2341 | | Last-Modified ; Section 14.29 | ||
2342 | | extension-header | ||
2343 | |||
2344 | extension-header = message-header | ||
2345 | |||
2346 | The extension-header mechanism allows additional entity-header fields | ||
2347 | to be defined without changing the protocol, but these fields cannot | ||
2348 | be assumed to be recognizable by the recipient. Unrecognized header | ||
2349 | fields SHOULD be ignored by the recipient and MUST be forwarded by | ||
2350 | transparent proxies. | ||
2351 | |||
2352 | |||
2353 | |||
2354 | Fielding, et al. Standards Track [Page 42] | ||
2355 | |||
2356 | RFC 2616 HTTP/1.1 June 1999 | ||
2357 | |||
2358 | |||
2359 | 7.2 Entity Body | ||
2360 | |||
2361 | The entity-body (if any) sent with an HTTP request or response is in | ||
2362 | a format and encoding defined by the entity-header fields. | ||
2363 | |||
2364 | entity-body = *OCTET | ||
2365 | |||
2366 | An entity-body is only present in a message when a message-body is | ||
2367 | present, as described in section 4.3. The entity-body is obtained | ||
2368 | from the message-body by decoding any Transfer-Encoding that might | ||
2369 | have been applied to ensure safe and proper transfer of the message. | ||
2370 | |||
2371 | 7.2.1 Type | ||
2372 | |||
2373 | When an entity-body is included with a message, the data type of that | ||
2374 | body is determined via the header fields Content-Type and Content- | ||
2375 | Encoding. These define a two-layer, ordered encoding model: | ||
2376 | |||
2377 | entity-body := Content-Encoding( Content-Type( data ) ) | ||
2378 | |||
2379 | Content-Type specifies the media type of the underlying data. | ||
2380 | Content-Encoding may be used to indicate any additional content | ||
2381 | codings applied to the data, usually for the purpose of data | ||
2382 | compression, that are a property of the requested resource. There is | ||
2383 | no default encoding. | ||
2384 | |||
2385 | Any HTTP/1.1 message containing an entity-body SHOULD include a | ||
2386 | Content-Type header field defining the media type of that body. If | ||
2387 | and only if the media type is not given by a Content-Type field, the | ||
2388 | recipient MAY attempt to guess the media type via inspection of its | ||
2389 | content and/or the name extension(s) of the URI used to identify the | ||
2390 | resource. If the media type remains unknown, the recipient SHOULD | ||
2391 | treat it as type "application/octet-stream". | ||
2392 | |||
2393 | 7.2.2 Entity Length | ||
2394 | |||
2395 | The entity-length of a message is the length of the message-body | ||
2396 | before any transfer-codings have been applied. Section 4.4 defines | ||
2397 | how the transfer-length of a message-body is determined. | ||
2398 | |||
2399 | |||
2400 | |||
2401 | |||
2402 | |||
2403 | |||
2404 | |||
2405 | |||
2406 | |||
2407 | |||
2408 | |||
2409 | |||
2410 | Fielding, et al. Standards Track [Page 43] | ||
2411 | |||
2412 | RFC 2616 HTTP/1.1 June 1999 | ||
2413 | |||
2414 | |||
2415 | 8 Connections | ||
2416 | |||
2417 | 8.1 Persistent Connections | ||
2418 | |||
2419 | 8.1.1 Purpose | ||
2420 | |||
2421 | Prior to persistent connections, a separate TCP connection was | ||
2422 | established to fetch each URL, increasing the load on HTTP servers | ||
2423 | and causing congestion on the Internet. The use of inline images and | ||
2424 | other associated data often require a client to make multiple | ||
2425 | requests of the same server in a short amount of time. Analysis of | ||
2426 | these performance problems and results from a prototype | ||
2427 | implementation are available [26] [30]. Implementation experience and | ||
2428 | measurements of actual HTTP/1.1 (RFC 2068) implementations show good | ||
2429 | results [39]. Alternatives have also been explored, for example, | ||
2430 | T/TCP [27]. | ||
2431 | |||
2432 | Persistent HTTP connections have a number of advantages: | ||
2433 | |||
2434 | - By opening and closing fewer TCP connections, CPU time is saved | ||
2435 | in routers and hosts (clients, servers, proxies, gateways, | ||
2436 | tunnels, or caches), and memory used for TCP protocol control | ||
2437 | blocks can be saved in hosts. | ||
2438 | |||
2439 | - HTTP requests and responses can be pipelined on a connection. | ||
2440 | Pipelining allows a client to make multiple requests without | ||
2441 | waiting for each response, allowing a single TCP connection to | ||
2442 | be used much more efficiently, with much lower elapsed time. | ||
2443 | |||
2444 | - Network congestion is reduced by reducing the number of packets | ||
2445 | caused by TCP opens, and by allowing TCP sufficient time to | ||
2446 | determine the congestion state of the network. | ||
2447 | |||
2448 | - Latency on subsequent requests is reduced since there is no time | ||
2449 | spent in TCP's connection opening handshake. | ||
2450 | |||
2451 | - HTTP can evolve more gracefully, since errors can be reported | ||
2452 | without the penalty of closing the TCP connection. Clients using | ||
2453 | future versions of HTTP might optimistically try a new feature, | ||
2454 | but if communicating with an older server, retry with old | ||
2455 | semantics after an error is reported. | ||
2456 | |||
2457 | HTTP implementations SHOULD implement persistent connections. | ||
2458 | |||
2459 | |||
2460 | |||
2461 | |||
2462 | |||
2463 | |||
2464 | |||
2465 | |||
2466 | Fielding, et al. Standards Track [Page 44] | ||
2467 | |||
2468 | RFC 2616 HTTP/1.1 June 1999 | ||
2469 | |||
2470 | |||
2471 | 8.1.2 Overall Operation | ||
2472 | |||
2473 | A significant difference between HTTP/1.1 and earlier versions of | ||
2474 | HTTP is that persistent connections are the default behavior of any | ||
2475 | HTTP connection. That is, unless otherwise indicated, the client | ||
2476 | SHOULD assume that the server will maintain a persistent connection, | ||
2477 | even after error responses from the server. | ||
2478 | |||
2479 | Persistent connections provide a mechanism by which a client and a | ||
2480 | server can signal the close of a TCP connection. This signaling takes | ||
2481 | place using the Connection header field (section 14.10). Once a close | ||
2482 | has been signaled, the client MUST NOT send any more requests on that | ||
2483 | connection. | ||
2484 | |||
2485 | 8.1.2.1 Negotiation | ||
2486 | |||
2487 | An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to | ||
2488 | maintain a persistent connection unless a Connection header including | ||
2489 | the connection-token "close" was sent in the request. If the server | ||
2490 | chooses to close the connection immediately after sending the | ||
2491 | response, it SHOULD send a Connection header including the | ||
2492 | connection-token close. | ||
2493 | |||
2494 | An HTTP/1.1 client MAY expect a connection to remain open, but would | ||
2495 | decide to keep it open based on whether the response from a server | ||
2496 | contains a Connection header with the connection-token close. In case | ||
2497 | the client does not want to maintain a connection for more than that | ||
2498 | request, it SHOULD send a Connection header including the | ||
2499 | connection-token close. | ||
2500 | |||
2501 | If either the client or the server sends the close token in the | ||
2502 | Connection header, that request becomes the last one for the | ||
2503 | connection. | ||
2504 | |||
2505 | Clients and servers SHOULD NOT assume that a persistent connection is | ||
2506 | maintained for HTTP versions less than 1.1 unless it is explicitly | ||
2507 | signaled. See section 19.6.2 for more information on backward | ||
2508 | compatibility with HTTP/1.0 clients. | ||
2509 | |||
2510 | In order to remain persistent, all messages on the connection MUST | ||
2511 | have a self-defined message length (i.e., one not defined by closure | ||
2512 | of the connection), as described in section 4.4. | ||
2513 | |||
2514 | |||
2515 | |||
2516 | |||
2517 | |||
2518 | |||
2519 | |||
2520 | |||
2521 | |||
2522 | Fielding, et al. Standards Track [Page 45] | ||
2523 | |||
2524 | RFC 2616 HTTP/1.1 June 1999 | ||
2525 | |||
2526 | |||
2527 | 8.1.2.2 Pipelining | ||
2528 | |||
2529 | A client that supports persistent connections MAY "pipeline" its | ||
2530 | requests (i.e., send multiple requests without waiting for each | ||
2531 | response). A server MUST send its responses to those requests in the | ||
2532 | same order that the requests were received. | ||
2533 | |||
2534 | Clients which assume persistent connections and pipeline immediately | ||
2535 | after connection establishment SHOULD be prepared to retry their | ||
2536 | connection if the first pipelined attempt fails. If a client does | ||
2537 | such a retry, it MUST NOT pipeline before it knows the connection is | ||
2538 | persistent. Clients MUST also be prepared to resend their requests if | ||
2539 | the server closes the connection before sending all of the | ||
2540 | corresponding responses. | ||
2541 | |||
2542 | Clients SHOULD NOT pipeline requests using non-idempotent methods or | ||
2543 | non-idempotent sequences of methods (see section 9.1.2). Otherwise, a | ||
2544 | premature termination of the transport connection could lead to | ||
2545 | indeterminate results. A client wishing to send a non-idempotent | ||
2546 | request SHOULD wait to send that request until it has received the | ||
2547 | response status for the previous request. | ||
2548 | |||
2549 | 8.1.3 Proxy Servers | ||
2550 | |||
2551 | It is especially important that proxies correctly implement the | ||
2552 | properties of the Connection header field as specified in section | ||
2553 | 14.10. | ||
2554 | |||
2555 | The proxy server MUST signal persistent connections separately with | ||
2556 | its clients and the origin servers (or other proxy servers) that it | ||
2557 | connects to. Each persistent connection applies to only one transport | ||
2558 | link. | ||
2559 | |||
2560 | A proxy server MUST NOT establish a HTTP/1.1 persistent connection | ||
2561 | with an HTTP/1.0 client (but see RFC 2068 [33] for information and | ||
2562 | discussion of the problems with the Keep-Alive header implemented by | ||
2563 | many HTTP/1.0 clients). | ||
2564 | |||
2565 | 8.1.4 Practical Considerations | ||
2566 | |||
2567 | Servers will usually have some time-out value beyond which they will | ||
2568 | no longer maintain an inactive connection. Proxy servers might make | ||
2569 | this a higher value since it is likely that the client will be making | ||
2570 | more connections through the same server. The use of persistent | ||
2571 | connections places no requirements on the length (or existence) of | ||
2572 | this time-out for either the client or the server. | ||
2573 | |||
2574 | |||
2575 | |||
2576 | |||
2577 | |||
2578 | Fielding, et al. Standards Track [Page 46] | ||
2579 | |||
2580 | RFC 2616 HTTP/1.1 June 1999 | ||
2581 | |||
2582 | |||
2583 | When a client or server wishes to time-out it SHOULD issue a graceful | ||
2584 | close on the transport connection. Clients and servers SHOULD both | ||
2585 | constantly watch for the other side of the transport close, and | ||
2586 | respond to it as appropriate. If a client or server does not detect | ||
2587 | the other side's close promptly it could cause unnecessary resource | ||
2588 | drain on the network. | ||
2589 | |||
2590 | A client, server, or proxy MAY close the transport connection at any | ||
2591 | time. For example, a client might have started to send a new request | ||
2592 | at the same time that the server has decided to close the "idle" | ||
2593 | connection. From the server's point of view, the connection is being | ||
2594 | closed while it was idle, but from the client's point of view, a | ||
2595 | request is in progress. | ||
2596 | |||
2597 | This means that clients, servers, and proxies MUST be able to recover | ||
2598 | from asynchronous close events. Client software SHOULD reopen the | ||
2599 | transport connection and retransmit the aborted sequence of requests | ||
2600 | without user interaction so long as the request sequence is | ||
2601 | idempotent (see section 9.1.2). Non-idempotent methods or sequences | ||
2602 | MUST NOT be automatically retried, although user agents MAY offer a | ||
2603 | human operator the choice of retrying the request(s). Confirmation by | ||
2604 | user-agent software with semantic understanding of the application | ||
2605 | MAY substitute for user confirmation. The automatic retry SHOULD NOT | ||
2606 | be repeated if the second sequence of requests fails. | ||
2607 | |||
2608 | Servers SHOULD always respond to at least one request per connection, | ||
2609 | if at all possible. Servers SHOULD NOT close a connection in the | ||
2610 | middle of transmitting a response, unless a network or client failure | ||
2611 | is suspected. | ||
2612 | |||
2613 | Clients that use persistent connections SHOULD limit the number of | ||
2614 | simultaneous connections that they maintain to a given server. A | ||
2615 | single-user client SHOULD NOT maintain more than 2 connections with | ||
2616 | any server or proxy. A proxy SHOULD use up to 2*N connections to | ||
2617 | another server or proxy, where N is the number of simultaneously | ||
2618 | active users. These guidelines are intended to improve HTTP response | ||
2619 | times and avoid congestion. | ||
2620 | |||
2621 | 8.2 Message Transmission Requirements | ||
2622 | |||
2623 | 8.2.1 Persistent Connections and Flow Control | ||
2624 | |||
2625 | HTTP/1.1 servers SHOULD maintain persistent connections and use TCP's | ||
2626 | flow control mechanisms to resolve temporary overloads, rather than | ||
2627 | terminating connections with the expectation that clients will retry. | ||
2628 | The latter technique can exacerbate network congestion. | ||
2629 | |||
2630 | |||
2631 | |||
2632 | |||
2633 | |||
2634 | Fielding, et al. Standards Track [Page 47] | ||
2635 | |||
2636 | RFC 2616 HTTP/1.1 June 1999 | ||
2637 | |||
2638 | |||
2639 | 8.2.2 Monitoring Connections for Error Status Messages | ||
2640 | |||
2641 | An HTTP/1.1 (or later) client sending a message-body SHOULD monitor | ||
2642 | the network connection for an error status while it is transmitting | ||
2643 | the request. If the client sees an error status, it SHOULD | ||
2644 | immediately cease transmitting the body. If the body is being sent | ||
2645 | using a "chunked" encoding (section 3.6), a zero length chunk and | ||
2646 | empty trailer MAY be used to prematurely mark the end of the message. | ||
2647 | If the body was preceded by a Content-Length header, the client MUST | ||
2648 | close the connection. | ||
2649 | |||
2650 | 8.2.3 Use of the 100 (Continue) Status | ||
2651 | |||
2652 | The purpose of the 100 (Continue) status (see section 10.1.1) is to | ||
2653 | allow a client that is sending a request message with a request body | ||
2654 | to determine if the origin server is willing to accept the request | ||
2655 | (based on the request headers) before the client sends the request | ||
2656 | body. In some cases, it might either be inappropriate or highly | ||
2657 | inefficient for the client to send the body if the server will reject | ||
2658 | the message without looking at the body. | ||
2659 | |||
2660 | Requirements for HTTP/1.1 clients: | ||
2661 | |||
2662 | - If a client will wait for a 100 (Continue) response before | ||
2663 | sending the request body, it MUST send an Expect request-header | ||
2664 | field (section 14.20) with the "100-continue" expectation. | ||
2665 | |||
2666 | - A client MUST NOT send an Expect request-header field (section | ||
2667 | 14.20) with the "100-continue" expectation if it does not intend | ||
2668 | to send a request body. | ||
2669 | |||
2670 | Because of the presence of older implementations, the protocol allows | ||
2671 | ambiguous situations in which a client may send "Expect: 100- | ||
2672 | continue" without receiving either a 417 (Expectation Failed) status | ||
2673 | or a 100 (Continue) status. Therefore, when a client sends this | ||
2674 | header field to an origin server (possibly via a proxy) from which it | ||
2675 | has never seen a 100 (Continue) status, the client SHOULD NOT wait | ||
2676 | for an indefinite period before sending the request body. | ||
2677 | |||
2678 | Requirements for HTTP/1.1 origin servers: | ||
2679 | |||
2680 | - Upon receiving a request which includes an Expect request-header | ||
2681 | field with the "100-continue" expectation, an origin server MUST | ||
2682 | either respond with 100 (Continue) status and continue to read | ||
2683 | from the input stream, or respond with a final status code. The | ||
2684 | origin server MUST NOT wait for the request body before sending | ||
2685 | the 100 (Continue) response. If it responds with a final status | ||
2686 | code, it MAY close the transport connection or it MAY continue | ||
2687 | |||
2688 | |||
2689 | |||
2690 | Fielding, et al. Standards Track [Page 48] | ||
2691 | |||
2692 | RFC 2616 HTTP/1.1 June 1999 | ||
2693 | |||
2694 | |||
2695 | to read and discard the rest of the request. It MUST NOT | ||
2696 | perform the requested method if it returns a final status code. | ||
2697 | |||
2698 | - An origin server SHOULD NOT send a 100 (Continue) response if | ||
2699 | the request message does not include an Expect request-header | ||
2700 | field with the "100-continue" expectation, and MUST NOT send a | ||
2701 | 100 (Continue) response if such a request comes from an HTTP/1.0 | ||
2702 | (or earlier) client. There is an exception to this rule: for | ||
2703 | compatibility with RFC 2068, a server MAY send a 100 (Continue) | ||
2704 | status in response to an HTTP/1.1 PUT or POST request that does | ||
2705 | not include an Expect request-header field with the "100- | ||
2706 | continue" expectation. This exception, the purpose of which is | ||
2707 | to minimize any client processing delays associated with an | ||
2708 | undeclared wait for 100 (Continue) status, applies only to | ||
2709 | HTTP/1.1 requests, and not to requests with any other HTTP- | ||
2710 | version value. | ||
2711 | |||
2712 | - An origin server MAY omit a 100 (Continue) response if it has | ||
2713 | already received some or all of the request body for the | ||
2714 | corresponding request. | ||
2715 | |||
2716 | - An origin server that sends a 100 (Continue) response MUST | ||
2717 | ultimately send a final status code, once the request body is | ||
2718 | received and processed, unless it terminates the transport | ||
2719 | connection prematurely. | ||
2720 | |||
2721 | - If an origin server receives a request that does not include an | ||
2722 | Expect request-header field with the "100-continue" expectation, | ||
2723 | the request includes a request body, and the server responds | ||
2724 | with a final status code before reading the entire request body | ||
2725 | from the transport connection, then the server SHOULD NOT close | ||
2726 | the transport connection until it has read the entire request, | ||
2727 | or until the client closes the connection. Otherwise, the client | ||
2728 | might not reliably receive the response message. However, this | ||
2729 | requirement is not be construed as preventing a server from | ||
2730 | defending itself against denial-of-service attacks, or from | ||
2731 | badly broken client implementations. | ||
2732 | |||
2733 | Requirements for HTTP/1.1 proxies: | ||
2734 | |||
2735 | - If a proxy receives a request that includes an Expect request- | ||
2736 | header field with the "100-continue" expectation, and the proxy | ||
2737 | either knows that the next-hop server complies with HTTP/1.1 or | ||
2738 | higher, or does not know the HTTP version of the next-hop | ||
2739 | server, it MUST forward the request, including the Expect header | ||
2740 | field. | ||
2741 | |||
2742 | |||
2743 | |||
2744 | |||
2745 | |||
2746 | Fielding, et al. Standards Track [Page 49] | ||
2747 | |||
2748 | RFC 2616 HTTP/1.1 June 1999 | ||
2749 | |||
2750 | |||
2751 | - If the proxy knows that the version of the next-hop server is | ||
2752 | HTTP/1.0 or lower, it MUST NOT forward the request, and it MUST | ||
2753 | respond with a 417 (Expectation Failed) status. | ||
2754 | |||
2755 | - Proxies SHOULD maintain a cache recording the HTTP version | ||
2756 | numbers received from recently-referenced next-hop servers. | ||
2757 | |||
2758 | - A proxy MUST NOT forward a 100 (Continue) response if the | ||
2759 | request message was received from an HTTP/1.0 (or earlier) | ||
2760 | client and did not include an Expect request-header field with | ||
2761 | the "100-continue" expectation. This requirement overrides the | ||
2762 | general rule for forwarding of 1xx responses (see section 10.1). | ||
2763 | |||
2764 | 8.2.4 Client Behavior if Server Prematurely Closes Connection | ||
2765 | |||
2766 | If an HTTP/1.1 client sends a request which includes a request body, | ||
2767 | but which does not include an Expect request-header field with the | ||
2768 | "100-continue" expectation, and if the client is not directly | ||
2769 | connected to an HTTP/1.1 origin server, and if the client sees the | ||
2770 | connection close before receiving any status from the server, the | ||
2771 | client SHOULD retry the request. If the client does retry this | ||
2772 | request, it MAY use the following "binary exponential backoff" | ||
2773 | algorithm to be assured of obtaining a reliable response: | ||
2774 | |||
2775 | 1. Initiate a new connection to the server | ||
2776 | |||
2777 | 2. Transmit the request-headers | ||
2778 | |||
2779 | 3. Initialize a variable R to the estimated round-trip time to the | ||
2780 | server (e.g., based on the time it took to establish the | ||
2781 | connection), or to a constant value of 5 seconds if the round- | ||
2782 | trip time is not available. | ||
2783 | |||
2784 | 4. Compute T = R * (2**N), where N is the number of previous | ||
2785 | retries of this request. | ||
2786 | |||
2787 | 5. Wait either for an error response from the server, or for T | ||
2788 | seconds (whichever comes first) | ||
2789 | |||
2790 | 6. If no error response is received, after T seconds transmit the | ||
2791 | body of the request. | ||
2792 | |||
2793 | 7. If client sees that the connection is closed prematurely, | ||
2794 | repeat from step 1 until the request is accepted, an error | ||
2795 | response is received, or the user becomes impatient and | ||
2796 | terminates the retry process. | ||
2797 | |||
2798 | |||
2799 | |||
2800 | |||
2801 | |||
2802 | Fielding, et al. Standards Track [Page 50] | ||
2803 | |||
2804 | RFC 2616 HTTP/1.1 June 1999 | ||
2805 | |||
2806 | |||
2807 | If at any point an error status is received, the client | ||
2808 | |||
2809 | - SHOULD NOT continue and | ||
2810 | |||
2811 | - SHOULD close the connection if it has not completed sending the | ||
2812 | request message. | ||
2813 | |||
2814 | 9 Method Definitions | ||
2815 | |||
2816 | The set of common methods for HTTP/1.1 is defined below. Although | ||
2817 | this set can be expanded, additional methods cannot be assumed to | ||
2818 | share the same semantics for separately extended clients and servers. | ||
2819 | |||
2820 | The Host request-header field (section 14.23) MUST accompany all | ||
2821 | HTTP/1.1 requests. | ||
2822 | |||
2823 | 9.1 Safe and Idempotent Methods | ||
2824 | |||
2825 | 9.1.1 Safe Methods | ||
2826 | |||
2827 | Implementors should be aware that the software represents the user in | ||
2828 | their interactions over the Internet, and should be careful to allow | ||
2829 | the user to be aware of any actions they might take which may have an | ||
2830 | unexpected significance to themselves or others. | ||
2831 | |||
2832 | In particular, the convention has been established that the GET and | ||
2833 | HEAD methods SHOULD NOT have the significance of taking an action | ||
2834 | other than retrieval. These methods ought to be considered "safe". | ||
2835 | This allows user agents to represent other methods, such as POST, PUT | ||
2836 | and DELETE, in a special way, so that the user is made aware of the | ||
2837 | fact that a possibly unsafe action is being requested. | ||
2838 | |||
2839 | Naturally, it is not possible to ensure that the server does not | ||
2840 | generate side-effects as a result of performing a GET request; in | ||
2841 | fact, some dynamic resources consider that a feature. The important | ||
2842 | distinction here is that the user did not request the side-effects, | ||
2843 | so therefore cannot be held accountable for them. | ||
2844 | |||
2845 | 9.1.2 Idempotent Methods | ||
2846 | |||
2847 | Methods can also have the property of "idempotence" in that (aside | ||
2848 | from error or expiration issues) the side-effects of N > 0 identical | ||
2849 | requests is the same as for a single request. The methods GET, HEAD, | ||
2850 | PUT and DELETE share this property. Also, the methods OPTIONS and | ||
2851 | TRACE SHOULD NOT have side effects, and so are inherently idempotent. | ||
2852 | |||
2853 | |||
2854 | |||
2855 | |||
2856 | |||
2857 | |||
2858 | Fielding, et al. Standards Track [Page 51] | ||
2859 | |||
2860 | RFC 2616 HTTP/1.1 June 1999 | ||
2861 | |||
2862 | |||
2863 | However, it is possible that a sequence of several requests is non- | ||
2864 | idempotent, even if all of the methods executed in that sequence are | ||
2865 | idempotent. (A sequence is idempotent if a single execution of the | ||
2866 | entire sequence always yields a result that is not changed by a | ||
2867 | reexecution of all, or part, of that sequence.) For example, a | ||
2868 | sequence is non-idempotent if its result depends on a value that is | ||
2869 | later modified in the same sequence. | ||
2870 | |||
2871 | A sequence that never has side effects is idempotent, by definition | ||
2872 | (provided that no concurrent operations are being executed on the | ||
2873 | same set of resources). | ||
2874 | |||
2875 | 9.2 OPTIONS | ||
2876 | |||
2877 | The OPTIONS method represents a request for information about the | ||
2878 | communication options available on the request/response chain | ||
2879 | identified by the Request-URI. This method allows the client to | ||
2880 | determine the options and/or requirements associated with a resource, | ||
2881 | or the capabilities of a server, without implying a resource action | ||
2882 | or initiating a resource retrieval. | ||
2883 | |||
2884 | Responses to this method are not cacheable. | ||
2885 | |||
2886 | If the OPTIONS request includes an entity-body (as indicated by the | ||
2887 | presence of Content-Length or Transfer-Encoding), then the media type | ||
2888 | MUST be indicated by a Content-Type field. Although this | ||
2889 | specification does not define any use for such a body, future | ||
2890 | extensions to HTTP might use the OPTIONS body to make more detailed | ||
2891 | queries on the server. A server that does not support such an | ||
2892 | extension MAY discard the request body. | ||
2893 | |||
2894 | If the Request-URI is an asterisk ("*"), the OPTIONS request is | ||
2895 | intended to apply to the server in general rather than to a specific | ||
2896 | resource. Since a server's communication options typically depend on | ||
2897 | the resource, the "*" request is only useful as a "ping" or "no-op" | ||
2898 | type of method; it does nothing beyond allowing the client to test | ||
2899 | the capabilities of the server. For example, this can be used to test | ||
2900 | a proxy for HTTP/1.1 compliance (or lack thereof). | ||
2901 | |||
2902 | If the Request-URI is not an asterisk, the OPTIONS request applies | ||
2903 | only to the options that are available when communicating with that | ||
2904 | resource. | ||
2905 | |||
2906 | A 200 response SHOULD include any header fields that indicate | ||
2907 | optional features implemented by the server and applicable to that | ||
2908 | resource (e.g., Allow), possibly including extensions not defined by | ||
2909 | this specification. The response body, if any, SHOULD also include | ||
2910 | information about the communication options. The format for such a | ||
2911 | |||
2912 | |||
2913 | |||
2914 | Fielding, et al. Standards Track [Page 52] | ||
2915 | |||
2916 | RFC 2616 HTTP/1.1 June 1999 | ||
2917 | |||
2918 | |||
2919 | body is not defined by this specification, but might be defined by | ||
2920 | future extensions to HTTP. Content negotiation MAY be used to select | ||
2921 | the appropriate response format. If no response body is included, the | ||
2922 | response MUST include a Content-Length field with a field-value of | ||
2923 | "0". | ||
2924 | |||
2925 | The Max-Forwards request-header field MAY be used to target a | ||
2926 | specific proxy in the request chain. When a proxy receives an OPTIONS | ||
2927 | request on an absoluteURI for which request forwarding is permitted, | ||
2928 | the proxy MUST check for a Max-Forwards field. If the Max-Forwards | ||
2929 | field-value is zero ("0"), the proxy MUST NOT forward the message; | ||
2930 | instead, the proxy SHOULD respond with its own communication options. | ||
2931 | If the Max-Forwards field-value is an integer greater than zero, the | ||
2932 | proxy MUST decrement the field-value when it forwards the request. If | ||
2933 | no Max-Forwards field is present in the request, then the forwarded | ||
2934 | request MUST NOT include a Max-Forwards field. | ||
2935 | |||
2936 | 9.3 GET | ||
2937 | |||
2938 | The GET method means retrieve whatever information (in the form of an | ||
2939 | entity) is identified by the Request-URI. If the Request-URI refers | ||
2940 | to a data-producing process, it is the produced data which shall be | ||
2941 | returned as the entity in the response and not the source text of the | ||
2942 | process, unless that text happens to be the output of the process. | ||
2943 | |||
2944 | The semantics of the GET method change to a "conditional GET" if the | ||
2945 | request message includes an If-Modified-Since, If-Unmodified-Since, | ||
2946 | If-Match, If-None-Match, or If-Range header field. A conditional GET | ||
2947 | method requests that the entity be transferred only under the | ||
2948 | circumstances described by the conditional header field(s). The | ||
2949 | conditional GET method is intended to reduce unnecessary network | ||
2950 | usage by allowing cached entities to be refreshed without requiring | ||
2951 | multiple requests or transferring data already held by the client. | ||
2952 | |||
2953 | The semantics of the GET method change to a "partial GET" if the | ||
2954 | request message includes a Range header field. A partial GET requests | ||
2955 | that only part of the entity be transferred, as described in section | ||
2956 | 14.35. The partial GET method is intended to reduce unnecessary | ||
2957 | network usage by allowing partially-retrieved entities to be | ||
2958 | completed without transferring data already held by the client. | ||
2959 | |||
2960 | The response to a GET request is cacheable if and only if it meets | ||
2961 | the requirements for HTTP caching described in section 13. | ||
2962 | |||
2963 | See section 15.1.3 for security considerations when used for forms. | ||
2964 | |||
2965 | |||
2966 | |||
2967 | |||
2968 | |||
2969 | |||
2970 | Fielding, et al. Standards Track [Page 53] | ||
2971 | |||
2972 | RFC 2616 HTTP/1.1 June 1999 | ||
2973 | |||
2974 | |||
2975 | 9.4 HEAD | ||
2976 | |||
2977 | The HEAD method is identical to GET except that the server MUST NOT | ||
2978 | return a message-body in the response. The metainformation contained | ||
2979 | in the HTTP headers in response to a HEAD request SHOULD be identical | ||
2980 | to the information sent in response to a GET request. This method can | ||
2981 | be used for obtaining metainformation about the entity implied by the | ||
2982 | request without transferring the entity-body itself. This method is | ||
2983 | often used for testing hypertext links for validity, accessibility, | ||
2984 | and recent modification. | ||
2985 | |||
2986 | The response to a HEAD request MAY be cacheable in the sense that the | ||
2987 | information contained in the response MAY be used to update a | ||
2988 | previously cached entity from that resource. If the new field values | ||
2989 | indicate that the cached entity differs from the current entity (as | ||
2990 | would be indicated by a change in Content-Length, Content-MD5, ETag | ||
2991 | or Last-Modified), then the cache MUST treat the cache entry as | ||
2992 | stale. | ||
2993 | |||
2994 | 9.5 POST | ||
2995 | |||
2996 | The POST method is used to request that the origin server accept the | ||
2997 | entity enclosed in the request as a new subordinate of the resource | ||
2998 | identified by the Request-URI in the Request-Line. POST is designed | ||
2999 | to allow a uniform method to cover the following functions: | ||
3000 | |||
3001 | - Annotation of existing resources; | ||
3002 | |||
3003 | - Posting a message to a bulletin board, newsgroup, mailing list, | ||
3004 | or similar group of articles; | ||
3005 | |||
3006 | - Providing a block of data, such as the result of submitting a | ||
3007 | form, to a data-handling process; | ||
3008 | |||
3009 | - Extending a database through an append operation. | ||
3010 | |||
3011 | The actual function performed by the POST method is determined by the | ||
3012 | server and is usually dependent on the Request-URI. The posted entity | ||
3013 | is subordinate to that URI in the same way that a file is subordinate | ||
3014 | to a directory containing it, a news article is subordinate to a | ||
3015 | newsgroup to which it is posted, or a record is subordinate to a | ||
3016 | database. | ||
3017 | |||
3018 | The action performed by the POST method might not result in a | ||
3019 | resource that can be identified by a URI. In this case, either 200 | ||
3020 | (OK) or 204 (No Content) is the appropriate response status, | ||
3021 | depending on whether or not the response includes an entity that | ||
3022 | describes the result. | ||
3023 | |||
3024 | |||
3025 | |||
3026 | Fielding, et al. Standards Track [Page 54] | ||
3027 | |||
3028 | RFC 2616 HTTP/1.1 June 1999 | ||
3029 | |||
3030 | |||
3031 | If a resource has been created on the origin server, the response | ||
3032 | SHOULD be 201 (Created) and contain an entity which describes the | ||
3033 | status of the request and refers to the new resource, and a Location | ||
3034 | header (see section 14.30). | ||
3035 | |||
3036 | Responses to this method are not cacheable, unless the response | ||
3037 | includes appropriate Cache-Control or Expires header fields. However, | ||
3038 | the 303 (See Other) response can be used to direct the user agent to | ||
3039 | retrieve a cacheable resource. | ||
3040 | |||
3041 | POST requests MUST obey the message transmission requirements set out | ||
3042 | in section 8.2. | ||
3043 | |||
3044 | See section 15.1.3 for security considerations. | ||
3045 | |||
3046 | 9.6 PUT | ||
3047 | |||
3048 | The PUT method requests that the enclosed entity be stored under the | ||
3049 | supplied Request-URI. If the Request-URI refers to an already | ||
3050 | existing resource, the enclosed entity SHOULD be considered as a | ||
3051 | modified version of the one residing on the origin server. If the | ||
3052 | Request-URI does not point to an existing resource, and that URI is | ||
3053 | capable of being defined as a new resource by the requesting user | ||
3054 | agent, the origin server can create the resource with that URI. If a | ||
3055 | new resource is created, the origin server MUST inform the user agent | ||
3056 | via the 201 (Created) response. If an existing resource is modified, | ||
3057 | either the 200 (OK) or 204 (No Content) response codes SHOULD be sent | ||
3058 | to indicate successful completion of the request. If the resource | ||
3059 | could not be created or modified with the Request-URI, an appropriate | ||
3060 | error response SHOULD be given that reflects the nature of the | ||
3061 | problem. The recipient of the entity MUST NOT ignore any Content-* | ||
3062 | (e.g. Content-Range) headers that it does not understand or implement | ||
3063 | and MUST return a 501 (Not Implemented) response in such cases. | ||
3064 | |||
3065 | If the request passes through a cache and the Request-URI identifies | ||
3066 | one or more currently cached entities, those entries SHOULD be | ||
3067 | treated as stale. Responses to this method are not cacheable. | ||
3068 | |||
3069 | The fundamental difference between the POST and PUT requests is | ||
3070 | reflected in the different meaning of the Request-URI. The URI in a | ||
3071 | POST request identifies the resource that will handle the enclosed | ||
3072 | entity. That resource might be a data-accepting process, a gateway to | ||
3073 | some other protocol, or a separate entity that accepts annotations. | ||
3074 | In contrast, the URI in a PUT request identifies the entity enclosed | ||
3075 | with the request -- the user agent knows what URI is intended and the | ||
3076 | server MUST NOT attempt to apply the request to some other resource. | ||
3077 | If the server desires that the request be applied to a different URI, | ||
3078 | |||
3079 | |||
3080 | |||
3081 | |||
3082 | Fielding, et al. Standards Track [Page 55] | ||
3083 | |||
3084 | RFC 2616 HTTP/1.1 June 1999 | ||
3085 | |||
3086 | |||
3087 | it MUST send a 301 (Moved Permanently) response; the user agent MAY | ||
3088 | then make its own decision regarding whether or not to redirect the | ||
3089 | request. | ||
3090 | |||
3091 | A single resource MAY be identified by many different URIs. For | ||
3092 | example, an article might have a URI for identifying "the current | ||
3093 | version" which is separate from the URI identifying each particular | ||
3094 | version. In this case, a PUT request on a general URI might result in | ||
3095 | several other URIs being defined by the origin server. | ||
3096 | |||
3097 | HTTP/1.1 does not define how a PUT method affects the state of an | ||
3098 | origin server. | ||
3099 | |||
3100 | PUT requests MUST obey the message transmission requirements set out | ||
3101 | in section 8.2. | ||
3102 | |||
3103 | Unless otherwise specified for a particular entity-header, the | ||
3104 | entity-headers in the PUT request SHOULD be applied to the resource | ||
3105 | created or modified by the PUT. | ||
3106 | |||
3107 | 9.7 DELETE | ||
3108 | |||
3109 | The DELETE method requests that the origin server delete the resource | ||
3110 | identified by the Request-URI. This method MAY be overridden by human | ||
3111 | intervention (or other means) on the origin server. The client cannot | ||
3112 | be guaranteed that the operation has been carried out, even if the | ||
3113 | status code returned from the origin server indicates that the action | ||
3114 | has been completed successfully. However, the server SHOULD NOT | ||
3115 | indicate success unless, at the time the response is given, it | ||
3116 | intends to delete the resource or move it to an inaccessible | ||
3117 | location. | ||
3118 | |||
3119 | A successful response SHOULD be 200 (OK) if the response includes an | ||
3120 | entity describing the status, 202 (Accepted) if the action has not | ||
3121 | yet been enacted, or 204 (No Content) if the action has been enacted | ||
3122 | but the response does not include an entity. | ||
3123 | |||
3124 | If the request passes through a cache and the Request-URI identifies | ||
3125 | one or more currently cached entities, those entries SHOULD be | ||
3126 | treated as stale. Responses to this method are not cacheable. | ||
3127 | |||
3128 | 9.8 TRACE | ||
3129 | |||
3130 | The TRACE method is used to invoke a remote, application-layer loop- | ||
3131 | back of the request message. The final recipient of the request | ||
3132 | SHOULD reflect the message received back to the client as the | ||
3133 | entity-body of a 200 (OK) response. The final recipient is either the | ||
3134 | |||
3135 | |||
3136 | |||
3137 | |||
3138 | Fielding, et al. Standards Track [Page 56] | ||
3139 | |||
3140 | RFC 2616 HTTP/1.1 June 1999 | ||
3141 | |||
3142 | |||
3143 | origin server or the first proxy or gateway to receive a Max-Forwards | ||
3144 | value of zero (0) in the request (see section 14.31). A TRACE request | ||
3145 | MUST NOT include an entity. | ||
3146 | |||
3147 | TRACE allows the client to see what is being received at the other | ||
3148 | end of the request chain and use that data for testing or diagnostic | ||
3149 | information. The value of the Via header field (section 14.45) is of | ||
3150 | particular interest, since it acts as a trace of the request chain. | ||
3151 | Use of the Max-Forwards header field allows the client to limit the | ||
3152 | length of the request chain, which is useful for testing a chain of | ||
3153 | proxies forwarding messages in an infinite loop. | ||
3154 | |||
3155 | If the request is valid, the response SHOULD contain the entire | ||
3156 | request message in the entity-body, with a Content-Type of | ||
3157 | "message/http". Responses to this method MUST NOT be cached. | ||
3158 | |||
3159 | 9.9 CONNECT | ||
3160 | |||
3161 | This specification reserves the method name CONNECT for use with a | ||
3162 | proxy that can dynamically switch to being a tunnel (e.g. SSL | ||
3163 | tunneling [44]). | ||
3164 | |||
3165 | 10 Status Code Definitions | ||
3166 | |||
3167 | Each Status-Code is described below, including a description of which | ||
3168 | method(s) it can follow and any metainformation required in the | ||
3169 | response. | ||
3170 | |||
3171 | 10.1 Informational 1xx | ||
3172 | |||
3173 | This class of status code indicates a provisional response, | ||
3174 | consisting only of the Status-Line and optional headers, and is | ||
3175 | terminated by an empty line. There are no required headers for this | ||
3176 | class of status code. Since HTTP/1.0 did not define any 1xx status | ||
3177 | codes, servers MUST NOT send a 1xx response to an HTTP/1.0 client | ||
3178 | except under experimental conditions. | ||
3179 | |||
3180 | A client MUST be prepared to accept one or more 1xx status responses | ||
3181 | prior to a regular response, even if the client does not expect a 100 | ||
3182 | (Continue) status message. Unexpected 1xx status responses MAY be | ||
3183 | ignored by a user agent. | ||
3184 | |||
3185 | Proxies MUST forward 1xx responses, unless the connection between the | ||
3186 | proxy and its client has been closed, or unless the proxy itself | ||
3187 | requested the generation of the 1xx response. (For example, if a | ||
3188 | |||
3189 | |||
3190 | |||
3191 | |||
3192 | |||
3193 | |||
3194 | Fielding, et al. Standards Track [Page 57] | ||
3195 | |||
3196 | RFC 2616 HTTP/1.1 June 1999 | ||
3197 | |||
3198 | |||
3199 | proxy adds a "Expect: 100-continue" field when it forwards a request, | ||
3200 | then it need not forward the corresponding 100 (Continue) | ||
3201 | response(s).) | ||
3202 | |||
3203 | 10.1.1 100 Continue | ||
3204 | |||
3205 | The client SHOULD continue with its request. This interim response is | ||
3206 | used to inform the client that the initial part of the request has | ||
3207 | been received and has not yet been rejected by the server. The client | ||
3208 | SHOULD continue by sending the remainder of the request or, if the | ||
3209 | request has already been completed, ignore this response. The server | ||
3210 | MUST send a final response after the request has been completed. See | ||
3211 | section 8.2.3 for detailed discussion of the use and handling of this | ||
3212 | status code. | ||
3213 | |||
3214 | 10.1.2 101 Switching Protocols | ||
3215 | |||
3216 | The server understands and is willing to comply with the client's | ||
3217 | request, via the Upgrade message header field (section 14.42), for a | ||
3218 | change in the application protocol being used on this connection. The | ||
3219 | server will switch protocols to those defined by the response's | ||
3220 | Upgrade header field immediately after the empty line which | ||
3221 | terminates the 101 response. | ||
3222 | |||
3223 | The protocol SHOULD be switched only when it is advantageous to do | ||
3224 | so. For example, switching to a newer version of HTTP is advantageous | ||
3225 | over older versions, and switching to a real-time, synchronous | ||
3226 | protocol might be advantageous when delivering resources that use | ||
3227 | such features. | ||
3228 | |||
3229 | 10.2 Successful 2xx | ||
3230 | |||
3231 | This class of status code indicates that the client's request was | ||
3232 | successfully received, understood, and accepted. | ||
3233 | |||
3234 | 10.2.1 200 OK | ||
3235 | |||
3236 | The request has succeeded. The information returned with the response | ||
3237 | is dependent on the method used in the request, for example: | ||
3238 | |||
3239 | GET an entity corresponding to the requested resource is sent in | ||
3240 | the response; | ||
3241 | |||
3242 | HEAD the entity-header fields corresponding to the requested | ||
3243 | resource are sent in the response without any message-body; | ||
3244 | |||
3245 | POST an entity describing or containing the result of the action; | ||
3246 | |||
3247 | |||
3248 | |||
3249 | |||
3250 | Fielding, et al. Standards Track [Page 58] | ||
3251 | |||
3252 | RFC 2616 HTTP/1.1 June 1999 | ||
3253 | |||
3254 | |||
3255 | TRACE an entity containing the request message as received by the | ||
3256 | end server. | ||
3257 | |||
3258 | 10.2.2 201 Created | ||
3259 | |||
3260 | The request has been fulfilled and resulted in a new resource being | ||
3261 | created. The newly created resource can be referenced by the URI(s) | ||
3262 | returned in the entity of the response, with the most specific URI | ||
3263 | for the resource given by a Location header field. The response | ||
3264 | SHOULD include an entity containing a list of resource | ||
3265 | characteristics and location(s) from which the user or user agent can | ||
3266 | choose the one most appropriate. The entity format is specified by | ||
3267 | the media type given in the Content-Type header field. The origin | ||
3268 | server MUST create the resource before returning the 201 status code. | ||
3269 | If the action cannot be carried out immediately, the server SHOULD | ||
3270 | respond with 202 (Accepted) response instead. | ||
3271 | |||
3272 | A 201 response MAY contain an ETag response header field indicating | ||
3273 | the current value of the entity tag for the requested variant just | ||
3274 | created, see section 14.19. | ||
3275 | |||
3276 | 10.2.3 202 Accepted | ||
3277 | |||
3278 | The request has been accepted for processing, but the processing has | ||
3279 | not been completed. The request might or might not eventually be | ||
3280 | acted upon, as it might be disallowed when processing actually takes | ||
3281 | place. There is no facility for re-sending a status code from an | ||
3282 | asynchronous operation such as this. | ||
3283 | |||
3284 | The 202 response is intentionally non-committal. Its purpose is to | ||
3285 | allow a server to accept a request for some other process (perhaps a | ||
3286 | batch-oriented process that is only run once per day) without | ||
3287 | requiring that the user agent's connection to the server persist | ||
3288 | until the process is completed. The entity returned with this | ||
3289 | response SHOULD include an indication of the request's current status | ||
3290 | and either a pointer to a status monitor or some estimate of when the | ||
3291 | user can expect the request to be fulfilled. | ||
3292 | |||
3293 | 10.2.4 203 Non-Authoritative Information | ||
3294 | |||
3295 | The returned metainformation in the entity-header is not the | ||
3296 | definitive set as available from the origin server, but is gathered | ||
3297 | from a local or a third-party copy. The set presented MAY be a subset | ||
3298 | or superset of the original version. For example, including local | ||
3299 | annotation information about the resource might result in a superset | ||
3300 | of the metainformation known by the origin server. Use of this | ||
3301 | response code is not required and is only appropriate when the | ||
3302 | response would otherwise be 200 (OK). | ||
3303 | |||
3304 | |||
3305 | |||
3306 | Fielding, et al. Standards Track [Page 59] | ||
3307 | |||
3308 | RFC 2616 HTTP/1.1 June 1999 | ||
3309 | |||
3310 | |||
3311 | 10.2.5 204 No Content | ||
3312 | |||
3313 | The server has fulfilled the request but does not need to return an | ||
3314 | entity-body, and might want to return updated metainformation. The | ||
3315 | response MAY include new or updated metainformation in the form of | ||
3316 | entity-headers, which if present SHOULD be associated with the | ||
3317 | requested variant. | ||
3318 | |||
3319 | If the client is a user agent, it SHOULD NOT change its document view | ||
3320 | from that which caused the request to be sent. This response is | ||
3321 | primarily intended to allow input for actions to take place without | ||
3322 | causing a change to the user agent's active document view, although | ||
3323 | any new or updated metainformation SHOULD be applied to the document | ||
3324 | currently in the user agent's active view. | ||
3325 | |||
3326 | The 204 response MUST NOT include a message-body, and thus is always | ||
3327 | terminated by the first empty line after the header fields. | ||
3328 | |||
3329 | 10.2.6 205 Reset Content | ||
3330 | |||
3331 | The server has fulfilled the request and the user agent SHOULD reset | ||
3332 | the document view which caused the request to be sent. This response | ||
3333 | is primarily intended to allow input for actions to take place via | ||
3334 | user input, followed by a clearing of the form in which the input is | ||
3335 | given so that the user can easily initiate another input action. The | ||
3336 | response MUST NOT include an entity. | ||
3337 | |||
3338 | 10.2.7 206 Partial Content | ||
3339 | |||
3340 | The server has fulfilled the partial GET request for the resource. | ||
3341 | The request MUST have included a Range header field (section 14.35) | ||
3342 | indicating the desired range, and MAY have included an If-Range | ||
3343 | header field (section 14.27) to make the request conditional. | ||
3344 | |||
3345 | The response MUST include the following header fields: | ||
3346 | |||
3347 | - Either a Content-Range header field (section 14.16) indicating | ||
3348 | the range included with this response, or a multipart/byteranges | ||
3349 | Content-Type including Content-Range fields for each part. If a | ||
3350 | Content-Length header field is present in the response, its | ||
3351 | value MUST match the actual number of OCTETs transmitted in the | ||
3352 | message-body. | ||
3353 | |||
3354 | - Date | ||
3355 | |||
3356 | - ETag and/or Content-Location, if the header would have been sent | ||
3357 | in a 200 response to the same request | ||
3358 | |||
3359 | |||
3360 | |||
3361 | |||
3362 | Fielding, et al. Standards Track [Page 60] | ||
3363 | |||
3364 | RFC 2616 HTTP/1.1 June 1999 | ||
3365 | |||
3366 | |||
3367 | - Expires, Cache-Control, and/or Vary, if the field-value might | ||
3368 | differ from that sent in any previous response for the same | ||
3369 | variant | ||
3370 | |||
3371 | If the 206 response is the result of an If-Range request that used a | ||
3372 | strong cache validator (see section 13.3.3), the response SHOULD NOT | ||
3373 | include other entity-headers. If the response is the result of an | ||
3374 | If-Range request that used a weak validator, the response MUST NOT | ||
3375 | include other entity-headers; this prevents inconsistencies between | ||
3376 | cached entity-bodies and updated headers. Otherwise, the response | ||
3377 | MUST include all of the entity-headers that would have been returned | ||
3378 | with a 200 (OK) response to the same request. | ||
3379 | |||
3380 | A cache MUST NOT combine a 206 response with other previously cached | ||
3381 | content if the ETag or Last-Modified headers do not match exactly, | ||
3382 | see 13.5.4. | ||
3383 | |||
3384 | A cache that does not support the Range and Content-Range headers | ||
3385 | MUST NOT cache 206 (Partial) responses. | ||
3386 | |||
3387 | 10.3 Redirection 3xx | ||
3388 | |||
3389 | This class of status code indicates that further action needs to be | ||
3390 | taken by the user agent in order to fulfill the request. The action | ||
3391 | required MAY be carried out by the user agent without interaction | ||
3392 | with the user if and only if the method used in the second request is | ||
3393 | GET or HEAD. A client SHOULD detect infinite redirection loops, since | ||
3394 | such loops generate network traffic for each redirection. | ||
3395 | |||
3396 | Note: previous versions of this specification recommended a | ||
3397 | maximum of five redirections. Content developers should be aware | ||
3398 | that there might be clients that implement such a fixed | ||
3399 | limitation. | ||
3400 | |||
3401 | 10.3.1 300 Multiple Choices | ||
3402 | |||
3403 | The requested resource corresponds to any one of a set of | ||
3404 | representations, each with its own specific location, and agent- | ||
3405 | driven negotiation information (section 12) is being provided so that | ||
3406 | the user (or user agent) can select a preferred representation and | ||
3407 | redirect its request to that location. | ||
3408 | |||
3409 | Unless it was a HEAD request, the response SHOULD include an entity | ||
3410 | containing a list of resource characteristics and location(s) from | ||
3411 | which the user or user agent can choose the one most appropriate. The | ||
3412 | entity format is specified by the media type given in the Content- | ||
3413 | Type header field. Depending upon the format and the capabilities of | ||
3414 | |||
3415 | |||
3416 | |||
3417 | |||
3418 | Fielding, et al. Standards Track [Page 61] | ||
3419 | |||
3420 | RFC 2616 HTTP/1.1 June 1999 | ||
3421 | |||
3422 | |||
3423 | the user agent, selection of the most appropriate choice MAY be | ||
3424 | performed automatically. However, this specification does not define | ||
3425 | any standard for such automatic selection. | ||
3426 | |||
3427 | If the server has a preferred choice of representation, it SHOULD | ||
3428 | include the specific URI for that representation in the Location | ||
3429 | field; user agents MAY use the Location field value for automatic | ||
3430 | redirection. This response is cacheable unless indicated otherwise. | ||
3431 | |||
3432 | 10.3.2 301 Moved Permanently | ||
3433 | |||
3434 | The requested resource has been assigned a new permanent URI and any | ||
3435 | future references to this resource SHOULD use one of the returned | ||
3436 | URIs. Clients with link editing capabilities ought to automatically | ||
3437 | re-link references to the Request-URI to one or more of the new | ||
3438 | references returned by the server, where possible. This response is | ||
3439 | cacheable unless indicated otherwise. | ||
3440 | |||
3441 | The new permanent URI SHOULD be given by the Location field in the | ||
3442 | response. Unless the request method was HEAD, the entity of the | ||
3443 | response SHOULD contain a short hypertext note with a hyperlink to | ||
3444 | the new URI(s). | ||
3445 | |||
3446 | If the 301 status code is received in response to a request other | ||
3447 | than GET or HEAD, the user agent MUST NOT automatically redirect the | ||
3448 | request unless it can be confirmed by the user, since this might | ||
3449 | change the conditions under which the request was issued. | ||
3450 | |||
3451 | Note: When automatically redirecting a POST request after | ||
3452 | receiving a 301 status code, some existing HTTP/1.0 user agents | ||
3453 | will erroneously change it into a GET request. | ||
3454 | |||
3455 | 10.3.3 302 Found | ||
3456 | |||
3457 | The requested resource resides temporarily under a different URI. | ||
3458 | Since the redirection might be altered on occasion, the client SHOULD | ||
3459 | continue to use the Request-URI for future requests. This response | ||
3460 | is only cacheable if indicated by a Cache-Control or Expires header | ||
3461 | field. | ||
3462 | |||
3463 | The temporary URI SHOULD be given by the Location field in the | ||
3464 | response. Unless the request method was HEAD, the entity of the | ||
3465 | response SHOULD contain a short hypertext note with a hyperlink to | ||
3466 | the new URI(s). | ||
3467 | |||
3468 | |||
3469 | |||
3470 | |||
3471 | |||
3472 | |||
3473 | |||
3474 | Fielding, et al. Standards Track [Page 62] | ||
3475 | |||
3476 | RFC 2616 HTTP/1.1 June 1999 | ||
3477 | |||
3478 | |||
3479 | If the 302 status code is received in response to a request other | ||
3480 | than GET or HEAD, the user agent MUST NOT automatically redirect the | ||
3481 | request unless it can be confirmed by the user, since this might | ||
3482 | change the conditions under which the request was issued. | ||
3483 | |||
3484 | Note: RFC 1945 and RFC 2068 specify that the client is not allowed | ||
3485 | to change the method on the redirected request. However, most | ||
3486 | existing user agent implementations treat 302 as if it were a 303 | ||
3487 | response, performing a GET on the Location field-value regardless | ||
3488 | of the original request method. The status codes 303 and 307 have | ||
3489 | been added for servers that wish to make unambiguously clear which | ||
3490 | kind of reaction is expected of the client. | ||
3491 | |||
3492 | 10.3.4 303 See Other | ||
3493 | |||
3494 | The response to the request can be found under a different URI and | ||
3495 | SHOULD be retrieved using a GET method on that resource. This method | ||
3496 | exists primarily to allow the output of a POST-activated script to | ||
3497 | redirect the user agent to a selected resource. The new URI is not a | ||
3498 | substitute reference for the originally requested resource. The 303 | ||
3499 | response MUST NOT be cached, but the response to the second | ||
3500 | (redirected) request might be cacheable. | ||
3501 | |||
3502 | The different URI SHOULD be given by the Location field in the | ||
3503 | response. Unless the request method was HEAD, the entity of the | ||
3504 | response SHOULD contain a short hypertext note with a hyperlink to | ||
3505 | the new URI(s). | ||
3506 | |||
3507 | Note: Many pre-HTTP/1.1 user agents do not understand the 303 | ||
3508 | status. When interoperability with such clients is a concern, the | ||
3509 | 302 status code may be used instead, since most user agents react | ||
3510 | to a 302 response as described here for 303. | ||
3511 | |||
3512 | 10.3.5 304 Not Modified | ||
3513 | |||
3514 | If the client has performed a conditional GET request and access is | ||
3515 | allowed, but the document has not been modified, the server SHOULD | ||
3516 | respond with this status code. The 304 response MUST NOT contain a | ||
3517 | message-body, and thus is always terminated by the first empty line | ||
3518 | after the header fields. | ||
3519 | |||
3520 | The response MUST include the following header fields: | ||
3521 | |||
3522 | - Date, unless its omission is required by section 14.18.1 | ||
3523 | |||
3524 | |||
3525 | |||
3526 | |||
3527 | |||
3528 | |||
3529 | |||
3530 | Fielding, et al. Standards Track [Page 63] | ||
3531 | |||
3532 | RFC 2616 HTTP/1.1 June 1999 | ||
3533 | |||
3534 | |||
3535 | If a clockless origin server obeys these rules, and proxies and | ||
3536 | clients add their own Date to any response received without one (as | ||
3537 | already specified by [RFC 2068], section 14.19), caches will operate | ||
3538 | correctly. | ||
3539 | |||
3540 | - ETag and/or Content-Location, if the header would have been sent | ||
3541 | in a 200 response to the same request | ||
3542 | |||
3543 | - Expires, Cache-Control, and/or Vary, if the field-value might | ||
3544 | differ from that sent in any previous response for the same | ||
3545 | variant | ||
3546 | |||
3547 | If the conditional GET used a strong cache validator (see section | ||
3548 | 13.3.3), the response SHOULD NOT include other entity-headers. | ||
3549 | Otherwise (i.e., the conditional GET used a weak validator), the | ||
3550 | response MUST NOT include other entity-headers; this prevents | ||
3551 | inconsistencies between cached entity-bodies and updated headers. | ||
3552 | |||
3553 | If a 304 response indicates an entity not currently cached, then the | ||
3554 | cache MUST disregard the response and repeat the request without the | ||
3555 | conditional. | ||
3556 | |||
3557 | If a cache uses a received 304 response to update a cache entry, the | ||
3558 | cache MUST update the entry to reflect any new field values given in | ||
3559 | the response. | ||
3560 | |||
3561 | 10.3.6 305 Use Proxy | ||
3562 | |||
3563 | The requested resource MUST be accessed through the proxy given by | ||
3564 | the Location field. The Location field gives the URI of the proxy. | ||
3565 | The recipient is expected to repeat this single request via the | ||
3566 | proxy. 305 responses MUST only be generated by origin servers. | ||
3567 | |||
3568 | Note: RFC 2068 was not clear that 305 was intended to redirect a | ||
3569 | single request, and to be generated by origin servers only. Not | ||
3570 | observing these limitations has significant security consequences. | ||
3571 | |||
3572 | 10.3.7 306 (Unused) | ||
3573 | |||
3574 | The 306 status code was used in a previous version of the | ||
3575 | specification, is no longer used, and the code is reserved. | ||
3576 | |||
3577 | |||
3578 | |||
3579 | |||
3580 | |||
3581 | |||
3582 | |||
3583 | |||
3584 | |||
3585 | |||
3586 | Fielding, et al. Standards Track [Page 64] | ||
3587 | |||
3588 | RFC 2616 HTTP/1.1 June 1999 | ||
3589 | |||
3590 | |||
3591 | 10.3.8 307 Temporary Redirect | ||
3592 | |||
3593 | The requested resource resides temporarily under a different URI. | ||
3594 | Since the redirection MAY be altered on occasion, the client SHOULD | ||
3595 | continue to use the Request-URI for future requests. This response | ||
3596 | is only cacheable if indicated by a Cache-Control or Expires header | ||
3597 | field. | ||
3598 | |||
3599 | The temporary URI SHOULD be given by the Location field in the | ||
3600 | response. Unless the request method was HEAD, the entity of the | ||
3601 | response SHOULD contain a short hypertext note with a hyperlink to | ||
3602 | the new URI(s) , since many pre-HTTP/1.1 user agents do not | ||
3603 | understand the 307 status. Therefore, the note SHOULD contain the | ||
3604 | information necessary for a user to repeat the original request on | ||
3605 | the new URI. | ||
3606 | |||
3607 | If the 307 status code is received in response to a request other | ||
3608 | than GET or HEAD, the user agent MUST NOT automatically redirect the | ||
3609 | request unless it can be confirmed by the user, since this might | ||
3610 | change the conditions under which the request was issued. | ||
3611 | |||
3612 | 10.4 Client Error 4xx | ||
3613 | |||
3614 | The 4xx class of status code is intended for cases in which the | ||
3615 | client seems to have erred. Except when responding to a HEAD request, | ||
3616 | the server SHOULD include an entity containing an explanation of the | ||
3617 | error situation, and whether it is a temporary or permanent | ||
3618 | condition. These status codes are applicable to any request method. | ||
3619 | User agents SHOULD display any included entity to the user. | ||
3620 | |||
3621 | If the client is sending data, a server implementation using TCP | ||
3622 | SHOULD be careful to ensure that the client acknowledges receipt of | ||
3623 | the packet(s) containing the response, before the server closes the | ||
3624 | input connection. If the client continues sending data to the server | ||
3625 | after the close, the server's TCP stack will send a reset packet to | ||
3626 | the client, which may erase the client's unacknowledged input buffers | ||
3627 | before they can be read and interpreted by the HTTP application. | ||
3628 | |||
3629 | 10.4.1 400 Bad Request | ||
3630 | |||
3631 | The request could not be understood by the server due to malformed | ||
3632 | syntax. The client SHOULD NOT repeat the request without | ||
3633 | modifications. | ||
3634 | |||
3635 | |||
3636 | |||
3637 | |||
3638 | |||
3639 | |||
3640 | |||
3641 | |||
3642 | Fielding, et al. Standards Track [Page 65] | ||
3643 | |||
3644 | RFC 2616 HTTP/1.1 June 1999 | ||
3645 | |||
3646 | |||
3647 | 10.4.2 401 Unauthorized | ||
3648 | |||
3649 | The request requires user authentication. The response MUST include a | ||
3650 | WWW-Authenticate header field (section 14.47) containing a challenge | ||
3651 | applicable to the requested resource. The client MAY repeat the | ||
3652 | request with a suitable Authorization header field (section 14.8). If | ||
3653 | the request already included Authorization credentials, then the 401 | ||
3654 | response indicates that authorization has been refused for those | ||
3655 | credentials. If the 401 response contains the same challenge as the | ||
3656 | prior response, and the user agent has already attempted | ||
3657 | authentication at least once, then the user SHOULD be presented the | ||
3658 | entity that was given in the response, since that entity might | ||
3659 | include relevant diagnostic information. HTTP access authentication | ||
3660 | is explained in "HTTP Authentication: Basic and Digest Access | ||
3661 | Authentication" [43]. | ||
3662 | |||
3663 | 10.4.3 402 Payment Required | ||
3664 | |||
3665 | This code is reserved for future use. | ||
3666 | |||
3667 | 10.4.4 403 Forbidden | ||
3668 | |||
3669 | The server understood the request, but is refusing to fulfill it. | ||
3670 | Authorization will not help and the request SHOULD NOT be repeated. | ||
3671 | If the request method was not HEAD and the server wishes to make | ||
3672 | public why the request has not been fulfilled, it SHOULD describe the | ||
3673 | reason for the refusal in the entity. If the server does not wish to | ||
3674 | make this information available to the client, the status code 404 | ||
3675 | (Not Found) can be used instead. | ||
3676 | |||
3677 | 10.4.5 404 Not Found | ||
3678 | |||
3679 | The server has not found anything matching the Request-URI. No | ||
3680 | indication is given of whether the condition is temporary or | ||
3681 | permanent. The 410 (Gone) status code SHOULD be used if the server | ||
3682 | knows, through some internally configurable mechanism, that an old | ||
3683 | resource is permanently unavailable and has no forwarding address. | ||
3684 | This status code is commonly used when the server does not wish to | ||
3685 | reveal exactly why the request has been refused, or when no other | ||
3686 | response is applicable. | ||
3687 | |||
3688 | 10.4.6 405 Method Not Allowed | ||
3689 | |||
3690 | The method specified in the Request-Line is not allowed for the | ||
3691 | resource identified by the Request-URI. The response MUST include an | ||
3692 | Allow header containing a list of valid methods for the requested | ||
3693 | resource. | ||
3694 | |||
3695 | |||
3696 | |||
3697 | |||
3698 | Fielding, et al. Standards Track [Page 66] | ||
3699 | |||
3700 | RFC 2616 HTTP/1.1 June 1999 | ||
3701 | |||
3702 | |||
3703 | 10.4.7 406 Not Acceptable | ||
3704 | |||
3705 | The resource identified by the request is only capable of generating | ||
3706 | response entities which have content characteristics not acceptable | ||
3707 | according to the accept headers sent in the request. | ||
3708 | |||
3709 | Unless it was a HEAD request, the response SHOULD include an entity | ||
3710 | containing a list of available entity characteristics and location(s) | ||
3711 | from which the user or user agent can choose the one most | ||
3712 | appropriate. The entity format is specified by the media type given | ||
3713 | in the Content-Type header field. Depending upon the format and the | ||
3714 | capabilities of the user agent, selection of the most appropriate | ||
3715 | choice MAY be performed automatically. However, this specification | ||
3716 | does not define any standard for such automatic selection. | ||
3717 | |||
3718 | Note: HTTP/1.1 servers are allowed to return responses which are | ||
3719 | not acceptable according to the accept headers sent in the | ||
3720 | request. In some cases, this may even be preferable to sending a | ||
3721 | 406 response. User agents are encouraged to inspect the headers of | ||
3722 | an incoming response to determine if it is acceptable. | ||
3723 | |||
3724 | If the response could be unacceptable, a user agent SHOULD | ||
3725 | temporarily stop receipt of more data and query the user for a | ||
3726 | decision on further actions. | ||
3727 | |||
3728 | 10.4.8 407 Proxy Authentication Required | ||
3729 | |||
3730 | This code is similar to 401 (Unauthorized), but indicates that the | ||
3731 | client must first authenticate itself with the proxy. The proxy MUST | ||
3732 | return a Proxy-Authenticate header field (section 14.33) containing a | ||
3733 | challenge applicable to the proxy for the requested resource. The | ||
3734 | client MAY repeat the request with a suitable Proxy-Authorization | ||
3735 | header field (section 14.34). HTTP access authentication is explained | ||
3736 | in "HTTP Authentication: Basic and Digest Access Authentication" | ||
3737 | [43]. | ||
3738 | |||
3739 | 10.4.9 408 Request Timeout | ||
3740 | |||
3741 | The client did not produce a request within the time that the server | ||
3742 | was prepared to wait. The client MAY repeat the request without | ||
3743 | modifications at any later time. | ||
3744 | |||
3745 | 10.4.10 409 Conflict | ||
3746 | |||
3747 | The request could not be completed due to a conflict with the current | ||
3748 | state of the resource. This code is only allowed in situations where | ||
3749 | it is expected that the user might be able to resolve the conflict | ||
3750 | and resubmit the request. The response body SHOULD include enough | ||
3751 | |||
3752 | |||
3753 | |||
3754 | Fielding, et al. Standards Track [Page 67] | ||
3755 | |||
3756 | RFC 2616 HTTP/1.1 June 1999 | ||
3757 | |||
3758 | |||
3759 | information for the user to recognize the source of the conflict. | ||
3760 | Ideally, the response entity would include enough information for the | ||
3761 | user or user agent to fix the problem; however, that might not be | ||
3762 | possible and is not required. | ||
3763 | |||
3764 | Conflicts are most likely to occur in response to a PUT request. For | ||
3765 | example, if versioning were being used and the entity being PUT | ||
3766 | included changes to a resource which conflict with those made by an | ||
3767 | earlier (third-party) request, the server might use the 409 response | ||
3768 | to indicate that it can't complete the request. In this case, the | ||
3769 | response entity would likely contain a list of the differences | ||
3770 | between the two versions in a format defined by the response | ||
3771 | Content-Type. | ||
3772 | |||
3773 | 10.4.11 410 Gone | ||
3774 | |||
3775 | The requested resource is no longer available at the server and no | ||
3776 | forwarding address is known. This condition is expected to be | ||
3777 | considered permanent. Clients with link editing capabilities SHOULD | ||
3778 | delete references to the Request-URI after user approval. If the | ||
3779 | server does not know, or has no facility to determine, whether or not | ||
3780 | the condition is permanent, the status code 404 (Not Found) SHOULD be | ||
3781 | used instead. This response is cacheable unless indicated otherwise. | ||
3782 | |||
3783 | The 410 response is primarily intended to assist the task of web | ||
3784 | maintenance by notifying the recipient that the resource is | ||
3785 | intentionally unavailable and that the server owners desire that | ||
3786 | remote links to that resource be removed. Such an event is common for | ||
3787 | limited-time, promotional services and for resources belonging to | ||
3788 | individuals no longer working at the server's site. It is not | ||
3789 | necessary to mark all permanently unavailable resources as "gone" or | ||
3790 | to keep the mark for any length of time -- that is left to the | ||
3791 | discretion of the server owner. | ||
3792 | |||
3793 | 10.4.12 411 Length Required | ||
3794 | |||
3795 | The server refuses to accept the request without a defined Content- | ||
3796 | Length. The client MAY repeat the request if it adds a valid | ||
3797 | Content-Length header field containing the length of the message-body | ||
3798 | in the request message. | ||
3799 | |||
3800 | 10.4.13 412 Precondition Failed | ||
3801 | |||
3802 | The precondition given in one or more of the request-header fields | ||
3803 | evaluated to false when it was tested on the server. This response | ||
3804 | code allows the client to place preconditions on the current resource | ||
3805 | metainformation (header field data) and thus prevent the requested | ||
3806 | method from being applied to a resource other than the one intended. | ||
3807 | |||
3808 | |||
3809 | |||
3810 | Fielding, et al. Standards Track [Page 68] | ||
3811 | |||
3812 | RFC 2616 HTTP/1.1 June 1999 | ||
3813 | |||
3814 | |||
3815 | 10.4.14 413 Request Entity Too Large | ||
3816 | |||
3817 | The server is refusing to process a request because the request | ||
3818 | entity is larger than the server is willing or able to process. The | ||
3819 | server MAY close the connection to prevent the client from continuing | ||
3820 | the request. | ||
3821 | |||
3822 | If the condition is temporary, the server SHOULD include a Retry- | ||
3823 | After header field to indicate that it is temporary and after what | ||
3824 | time the client MAY try again. | ||
3825 | |||
3826 | 10.4.15 414 Request-URI Too Long | ||
3827 | |||
3828 | The server is refusing to service the request because the Request-URI | ||
3829 | is longer than the server is willing to interpret. This rare | ||
3830 | condition is only likely to occur when a client has improperly | ||
3831 | converted a POST request to a GET request with long query | ||
3832 | information, when the client has descended into a URI "black hole" of | ||
3833 | redirection (e.g., a redirected URI prefix that points to a suffix of | ||
3834 | itself), or when the server is under attack by a client attempting to | ||
3835 | exploit security holes present in some servers using fixed-length | ||
3836 | buffers for reading or manipulating the Request-URI. | ||
3837 | |||
3838 | 10.4.16 415 Unsupported Media Type | ||
3839 | |||
3840 | The server is refusing to service the request because the entity of | ||
3841 | the request is in a format not supported by the requested resource | ||
3842 | for the requested method. | ||
3843 | |||
3844 | 10.4.17 416 Requested Range Not Satisfiable | ||
3845 | |||
3846 | A server SHOULD return a response with this status code if a request | ||
3847 | included a Range request-header field (section 14.35), and none of | ||
3848 | the range-specifier values in this field overlap the current extent | ||
3849 | of the selected resource, and the request did not include an If-Range | ||
3850 | request-header field. (For byte-ranges, this means that the first- | ||
3851 | byte-pos of all of the byte-range-spec values were greater than the | ||
3852 | current length of the selected resource.) | ||
3853 | |||
3854 | When this status code is returned for a byte-range request, the | ||
3855 | response SHOULD include a Content-Range entity-header field | ||
3856 | specifying the current length of the selected resource (see section | ||
3857 | 14.16). This response MUST NOT use the multipart/byteranges content- | ||
3858 | type. | ||
3859 | |||
3860 | |||
3861 | |||
3862 | |||
3863 | |||
3864 | |||
3865 | |||
3866 | Fielding, et al. Standards Track [Page 69] | ||
3867 | |||
3868 | RFC 2616 HTTP/1.1 June 1999 | ||
3869 | |||
3870 | |||
3871 | 10.4.18 417 Expectation Failed | ||
3872 | |||
3873 | The expectation given in an Expect request-header field (see section | ||
3874 | 14.20) could not be met by this server, or, if the server is a proxy, | ||
3875 | the server has unambiguous evidence that the request could not be met | ||
3876 | by the next-hop server. | ||
3877 | |||
3878 | 10.5 Server Error 5xx | ||
3879 | |||
3880 | Response status codes beginning with the digit "5" indicate cases in | ||
3881 | which the server is aware that it has erred or is incapable of | ||
3882 | performing the request. Except when responding to a HEAD request, the | ||
3883 | server SHOULD include an entity containing an explanation of the | ||
3884 | error situation, and whether it is a temporary or permanent | ||
3885 | condition. User agents SHOULD display any included entity to the | ||
3886 | user. These response codes are applicable to any request method. | ||
3887 | |||
3888 | 10.5.1 500 Internal Server Error | ||
3889 | |||
3890 | The server encountered an unexpected condition which prevented it | ||
3891 | from fulfilling the request. | ||
3892 | |||
3893 | 10.5.2 501 Not Implemented | ||
3894 | |||
3895 | The server does not support the functionality required to fulfill the | ||
3896 | request. This is the appropriate response when the server does not | ||
3897 | recognize the request method and is not capable of supporting it for | ||
3898 | any resource. | ||
3899 | |||
3900 | 10.5.3 502 Bad Gateway | ||
3901 | |||
3902 | The server, while acting as a gateway or proxy, received an invalid | ||
3903 | response from the upstream server it accessed in attempting to | ||
3904 | fulfill the request. | ||
3905 | |||
3906 | 10.5.4 503 Service Unavailable | ||
3907 | |||
3908 | The server is currently unable to handle the request due to a | ||
3909 | temporary overloading or maintenance of the server. The implication | ||
3910 | is that this is a temporary condition which will be alleviated after | ||
3911 | some delay. If known, the length of the delay MAY be indicated in a | ||
3912 | Retry-After header. If no Retry-After is given, the client SHOULD | ||
3913 | handle the response as it would for a 500 response. | ||
3914 | |||
3915 | Note: The existence of the 503 status code does not imply that a | ||
3916 | server must use it when becoming overloaded. Some servers may wish | ||
3917 | to simply refuse the connection. | ||
3918 | |||
3919 | |||
3920 | |||
3921 | |||
3922 | Fielding, et al. Standards Track [Page 70] | ||
3923 | |||
3924 | RFC 2616 HTTP/1.1 June 1999 | ||
3925 | |||
3926 | |||
3927 | 10.5.5 504 Gateway Timeout | ||
3928 | |||
3929 | The server, while acting as a gateway or proxy, did not receive a | ||
3930 | timely response from the upstream server specified by the URI (e.g. | ||
3931 | HTTP, FTP, LDAP) or some other auxiliary server (e.g. DNS) it needed | ||
3932 | to access in attempting to complete the request. | ||
3933 | |||
3934 | Note: Note to implementors: some deployed proxies are known to | ||
3935 | return 400 or 500 when DNS lookups time out. | ||
3936 | |||
3937 | 10.5.6 505 HTTP Version Not Supported | ||
3938 | |||
3939 | The server does not support, or refuses to support, the HTTP protocol | ||
3940 | version that was used in the request message. The server is | ||
3941 | indicating that it is unable or unwilling to complete the request | ||
3942 | using the same major version as the client, as described in section | ||
3943 | 3.1, other than with this error message. The response SHOULD contain | ||
3944 | an entity describing why that version is not supported and what other | ||
3945 | protocols are supported by that server. | ||
3946 | |||
3947 | 11 Access Authentication | ||
3948 | |||
3949 | HTTP provides several OPTIONAL challenge-response authentication | ||
3950 | mechanisms which can be used by a server to challenge a client | ||
3951 | request and by a client to provide authentication information. The | ||
3952 | general framework for access authentication, and the specification of | ||
3953 | "basic" and "digest" authentication, are specified in "HTTP | ||
3954 | Authentication: Basic and Digest Access Authentication" [43]. This | ||
3955 | specification adopts the definitions of "challenge" and "credentials" | ||
3956 | from that specification. | ||
3957 | |||
3958 | 12 Content Negotiation | ||
3959 | |||
3960 | Most HTTP responses include an entity which contains information for | ||
3961 | interpretation by a human user. Naturally, it is desirable to supply | ||
3962 | the user with the "best available" entity corresponding to the | ||
3963 | request. Unfortunately for servers and caches, not all users have the | ||
3964 | same preferences for what is "best," and not all user agents are | ||
3965 | equally capable of rendering all entity types. For that reason, HTTP | ||
3966 | has provisions for several mechanisms for "content negotiation" -- | ||
3967 | the process of selecting the best representation for a given response | ||
3968 | when there are multiple representations available. | ||
3969 | |||
3970 | Note: This is not called "format negotiation" because the | ||
3971 | alternate representations may be of the same media type, but use | ||
3972 | different capabilities of that type, be in different languages, | ||
3973 | etc. | ||
3974 | |||
3975 | |||
3976 | |||
3977 | |||
3978 | Fielding, et al. Standards Track [Page 71] | ||
3979 | |||
3980 | RFC 2616 HTTP/1.1 June 1999 | ||
3981 | |||
3982 | |||
3983 | Any response containing an entity-body MAY be subject to negotiation, | ||
3984 | including error responses. | ||
3985 | |||
3986 | There are two kinds of content negotiation which are possible in | ||
3987 | HTTP: server-driven and agent-driven negotiation. These two kinds of | ||
3988 | negotiation are orthogonal and thus may be used separately or in | ||
3989 | combination. One method of combination, referred to as transparent | ||
3990 | negotiation, occurs when a cache uses the agent-driven negotiation | ||
3991 | information provided by the origin server in order to provide | ||
3992 | server-driven negotiation for subsequent requests. | ||
3993 | |||
3994 | 12.1 Server-driven Negotiation | ||
3995 | |||
3996 | If the selection of the best representation for a response is made by | ||
3997 | an algorithm located at the server, it is called server-driven | ||
3998 | negotiation. Selection is based on the available representations of | ||
3999 | the response (the dimensions over which it can vary; e.g. language, | ||
4000 | content-coding, etc.) and the contents of particular header fields in | ||
4001 | the request message or on other information pertaining to the request | ||
4002 | (such as the network address of the client). | ||
4003 | |||
4004 | Server-driven negotiation is advantageous when the algorithm for | ||
4005 | selecting from among the available representations is difficult to | ||
4006 | describe to the user agent, or when the server desires to send its | ||
4007 | "best guess" to the client along with the first response (hoping to | ||
4008 | avoid the round-trip delay of a subsequent request if the "best | ||
4009 | guess" is good enough for the user). In order to improve the server's | ||
4010 | guess, the user agent MAY include request header fields (Accept, | ||
4011 | Accept-Language, Accept-Encoding, etc.) which describe its | ||
4012 | preferences for such a response. | ||
4013 | |||
4014 | Server-driven negotiation has disadvantages: | ||
4015 | |||
4016 | 1. It is impossible for the server to accurately determine what | ||
4017 | might be "best" for any given user, since that would require | ||
4018 | complete knowledge of both the capabilities of the user agent | ||
4019 | and the intended use for the response (e.g., does the user want | ||
4020 | to view it on screen or print it on paper?). | ||
4021 | |||
4022 | 2. Having the user agent describe its capabilities in every | ||
4023 | request can be both very inefficient (given that only a small | ||
4024 | percentage of responses have multiple representations) and a | ||
4025 | potential violation of the user's privacy. | ||
4026 | |||
4027 | 3. It complicates the implementation of an origin server and the | ||
4028 | algorithms for generating responses to a request. | ||
4029 | |||
4030 | |||
4031 | |||
4032 | |||
4033 | |||
4034 | Fielding, et al. Standards Track [Page 72] | ||
4035 | |||
4036 | RFC 2616 HTTP/1.1 June 1999 | ||
4037 | |||
4038 | |||
4039 | 4. It may limit a public cache's ability to use the same response | ||
4040 | for multiple user's requests. | ||
4041 | |||
4042 | HTTP/1.1 includes the following request-header fields for enabling | ||
4043 | server-driven negotiation through description of user agent | ||
4044 | capabilities and user preferences: Accept (section 14.1), Accept- | ||
4045 | Charset (section 14.2), Accept-Encoding (section 14.3), Accept- | ||
4046 | Language (section 14.4), and User-Agent (section 14.43). However, an | ||
4047 | origin server is not limited to these dimensions and MAY vary the | ||
4048 | response based on any aspect of the request, including information | ||
4049 | outside the request-header fields or within extension header fields | ||
4050 | not defined by this specification. | ||
4051 | |||
4052 | The Vary header field can be used to express the parameters the | ||
4053 | server uses to select a representation that is subject to server- | ||
4054 | driven negotiation. See section 13.6 for use of the Vary header field | ||
4055 | by caches and section 14.44 for use of the Vary header field by | ||
4056 | servers. | ||
4057 | |||
4058 | 12.2 Agent-driven Negotiation | ||
4059 | |||
4060 | With agent-driven negotiation, selection of the best representation | ||
4061 | for a response is performed by the user agent after receiving an | ||
4062 | initial response from the origin server. Selection is based on a list | ||
4063 | of the available representations of the response included within the | ||
4064 | header fields or entity-body of the initial response, with each | ||
4065 | representation identified by its own URI. Selection from among the | ||
4066 | representations may be performed automatically (if the user agent is | ||
4067 | capable of doing so) or manually by the user selecting from a | ||
4068 | generated (possibly hypertext) menu. | ||
4069 | |||
4070 | Agent-driven negotiation is advantageous when the response would vary | ||
4071 | over commonly-used dimensions (such as type, language, or encoding), | ||
4072 | when the origin server is unable to determine a user agent's | ||
4073 | capabilities from examining the request, and generally when public | ||
4074 | caches are used to distribute server load and reduce network usage. | ||
4075 | |||
4076 | Agent-driven negotiation suffers from the disadvantage of needing a | ||
4077 | second request to obtain the best alternate representation. This | ||
4078 | second request is only efficient when caching is used. In addition, | ||
4079 | this specification does not define any mechanism for supporting | ||
4080 | automatic selection, though it also does not prevent any such | ||
4081 | mechanism from being developed as an extension and used within | ||
4082 | HTTP/1.1. | ||
4083 | |||
4084 | |||
4085 | |||
4086 | |||
4087 | |||
4088 | |||
4089 | |||
4090 | Fielding, et al. Standards Track [Page 73] | ||
4091 | |||
4092 | RFC 2616 HTTP/1.1 June 1999 | ||
4093 | |||
4094 | |||
4095 | HTTP/1.1 defines the 300 (Multiple Choices) and 406 (Not Acceptable) | ||
4096 | status codes for enabling agent-driven negotiation when the server is | ||
4097 | unwilling or unable to provide a varying response using server-driven | ||
4098 | negotiation. | ||
4099 | |||
4100 | 12.3 Transparent Negotiation | ||
4101 | |||
4102 | Transparent negotiation is a combination of both server-driven and | ||
4103 | agent-driven negotiation. When a cache is supplied with a form of the | ||
4104 | list of available representations of the response (as in agent-driven | ||
4105 | negotiation) and the dimensions of variance are completely understood | ||
4106 | by the cache, then the cache becomes capable of performing server- | ||
4107 | driven negotiation on behalf of the origin server for subsequent | ||
4108 | requests on that resource. | ||
4109 | |||
4110 | Transparent negotiation has the advantage of distributing the | ||
4111 | negotiation work that would otherwise be required of the origin | ||
4112 | server and also removing the second request delay of agent-driven | ||
4113 | negotiation when the cache is able to correctly guess the right | ||
4114 | response. | ||
4115 | |||
4116 | This specification does not define any mechanism for transparent | ||
4117 | negotiation, though it also does not prevent any such mechanism from | ||
4118 | being developed as an extension that could be used within HTTP/1.1. | ||
4119 | |||
4120 | 13 Caching in HTTP | ||
4121 | |||
4122 | HTTP is typically used for distributed information systems, where | ||
4123 | performance can be improved by the use of response caches. The | ||
4124 | HTTP/1.1 protocol includes a number of elements intended to make | ||
4125 | caching work as well as possible. Because these elements are | ||
4126 | inextricable from other aspects of the protocol, and because they | ||
4127 | interact with each other, it is useful to describe the basic caching | ||
4128 | design of HTTP separately from the detailed descriptions of methods, | ||
4129 | headers, response codes, etc. | ||
4130 | |||
4131 | Caching would be useless if it did not significantly improve | ||
4132 | performance. The goal of caching in HTTP/1.1 is to eliminate the need | ||
4133 | to send requests in many cases, and to eliminate the need to send | ||
4134 | full responses in many other cases. The former reduces the number of | ||
4135 | network round-trips required for many operations; we use an | ||
4136 | "expiration" mechanism for this purpose (see section 13.2). The | ||
4137 | latter reduces network bandwidth requirements; we use a "validation" | ||
4138 | mechanism for this purpose (see section 13.3). | ||
4139 | |||
4140 | Requirements for performance, availability, and disconnected | ||
4141 | operation require us to be able to relax the goal of semantic | ||
4142 | transparency. The HTTP/1.1 protocol allows origin servers, caches, | ||
4143 | |||
4144 | |||
4145 | |||
4146 | Fielding, et al. Standards Track [Page 74] | ||
4147 | |||
4148 | RFC 2616 HTTP/1.1 June 1999 | ||
4149 | |||
4150 | |||
4151 | and clients to explicitly reduce transparency when necessary. | ||
4152 | However, because non-transparent operation may confuse non-expert | ||
4153 | users, and might be incompatible with certain server applications | ||
4154 | (such as those for ordering merchandise), the protocol requires that | ||
4155 | transparency be relaxed | ||
4156 | |||
4157 | - only by an explicit protocol-level request when relaxed by | ||
4158 | client or origin server | ||
4159 | |||
4160 | - only with an explicit warning to the end user when relaxed by | ||
4161 | cache or client | ||
4162 | |||
4163 | Therefore, the HTTP/1.1 protocol provides these important elements: | ||
4164 | |||
4165 | 1. Protocol features that provide full semantic transparency when | ||
4166 | this is required by all parties. | ||
4167 | |||
4168 | 2. Protocol features that allow an origin server or user agent to | ||
4169 | explicitly request and control non-transparent operation. | ||
4170 | |||
4171 | 3. Protocol features that allow a cache to attach warnings to | ||
4172 | responses that do not preserve the requested approximation of | ||
4173 | semantic transparency. | ||
4174 | |||
4175 | A basic principle is that it must be possible for the clients to | ||
4176 | detect any potential relaxation of semantic transparency. | ||
4177 | |||
4178 | Note: The server, cache, or client implementor might be faced with | ||
4179 | design decisions not explicitly discussed in this specification. | ||
4180 | If a decision might affect semantic transparency, the implementor | ||
4181 | ought to err on the side of maintaining transparency unless a | ||
4182 | careful and complete analysis shows significant benefits in | ||
4183 | breaking transparency. | ||
4184 | |||
4185 | 13.1.1 Cache Correctness | ||
4186 | |||
4187 | A correct cache MUST respond to a request with the most up-to-date | ||
4188 | response held by the cache that is appropriate to the request (see | ||
4189 | sections 13.2.5, 13.2.6, and 13.12) which meets one of the following | ||
4190 | conditions: | ||
4191 | |||
4192 | 1. It has been checked for equivalence with what the origin server | ||
4193 | would have returned by revalidating the response with the | ||
4194 | origin server (section 13.3); | ||
4195 | |||
4196 | |||
4197 | |||
4198 | |||
4199 | |||
4200 | |||
4201 | |||
4202 | Fielding, et al. Standards Track [Page 75] | ||
4203 | |||
4204 | RFC 2616 HTTP/1.1 June 1999 | ||
4205 | |||
4206 | |||
4207 | 2. It is "fresh enough" (see section 13.2). In the default case, | ||
4208 | this means it meets the least restrictive freshness requirement | ||
4209 | of the client, origin server, and cache (see section 14.9); if | ||
4210 | the origin server so specifies, it is the freshness requirement | ||
4211 | of the origin server alone. | ||
4212 | |||
4213 | If a stored response is not "fresh enough" by the most | ||
4214 | restrictive freshness requirement of both the client and the | ||
4215 | origin server, in carefully considered circumstances the cache | ||
4216 | MAY still return the response with the appropriate Warning | ||
4217 | header (see section 13.1.5 and 14.46), unless such a response | ||
4218 | is prohibited (e.g., by a "no-store" cache-directive, or by a | ||
4219 | "no-cache" cache-request-directive; see section 14.9). | ||
4220 | |||
4221 | 3. It is an appropriate 304 (Not Modified), 305 (Proxy Redirect), | ||
4222 | or error (4xx or 5xx) response message. | ||
4223 | |||
4224 | If the cache can not communicate with the origin server, then a | ||
4225 | correct cache SHOULD respond as above if the response can be | ||
4226 | correctly served from the cache; if not it MUST return an error or | ||
4227 | warning indicating that there was a communication failure. | ||
4228 | |||
4229 | If a cache receives a response (either an entire response, or a 304 | ||
4230 | (Not Modified) response) that it would normally forward to the | ||
4231 | requesting client, and the received response is no longer fresh, the | ||
4232 | cache SHOULD forward it to the requesting client without adding a new | ||
4233 | Warning (but without removing any existing Warning headers). A cache | ||
4234 | SHOULD NOT attempt to revalidate a response simply because that | ||
4235 | response became stale in transit; this might lead to an infinite | ||
4236 | loop. A user agent that receives a stale response without a Warning | ||
4237 | MAY display a warning indication to the user. | ||
4238 | |||
4239 | 13.1.2 Warnings | ||
4240 | |||
4241 | Whenever a cache returns a response that is neither first-hand nor | ||
4242 | "fresh enough" (in the sense of condition 2 in section 13.1.1), it | ||
4243 | MUST attach a warning to that effect, using a Warning general-header. | ||
4244 | The Warning header and the currently defined warnings are described | ||
4245 | in section 14.46. The warning allows clients to take appropriate | ||
4246 | action. | ||
4247 | |||
4248 | Warnings MAY be used for other purposes, both cache-related and | ||
4249 | otherwise. The use of a warning, rather than an error status code, | ||
4250 | distinguish these responses from true failures. | ||
4251 | |||
4252 | Warnings are assigned three digit warn-codes. The first digit | ||
4253 | indicates whether the Warning MUST or MUST NOT be deleted from a | ||
4254 | stored cache entry after a successful revalidation: | ||
4255 | |||
4256 | |||
4257 | |||
4258 | Fielding, et al. Standards Track [Page 76] | ||
4259 | |||
4260 | RFC 2616 HTTP/1.1 June 1999 | ||
4261 | |||
4262 | |||
4263 | 1xx Warnings that describe the freshness or revalidation status of | ||
4264 | the response, and so MUST be deleted after a successful | ||
4265 | revalidation. 1XX warn-codes MAY be generated by a cache only when | ||
4266 | validating a cached entry. It MUST NOT be generated by clients. | ||
4267 | |||
4268 | 2xx Warnings that describe some aspect of the entity body or entity | ||
4269 | headers that is not rectified by a revalidation (for example, a | ||
4270 | lossy compression of the entity bodies) and which MUST NOT be | ||
4271 | deleted after a successful revalidation. | ||
4272 | |||
4273 | See section 14.46 for the definitions of the codes themselves. | ||
4274 | |||
4275 | HTTP/1.0 caches will cache all Warnings in responses, without | ||
4276 | deleting the ones in the first category. Warnings in responses that | ||
4277 | are passed to HTTP/1.0 caches carry an extra warning-date field, | ||
4278 | which prevents a future HTTP/1.1 recipient from believing an | ||
4279 | erroneously cached Warning. | ||
4280 | |||
4281 | Warnings also carry a warning text. The text MAY be in any | ||
4282 | appropriate natural language (perhaps based on the client's Accept | ||
4283 | headers), and include an OPTIONAL indication of what character set is | ||
4284 | used. | ||
4285 | |||
4286 | Multiple warnings MAY be attached to a response (either by the origin | ||
4287 | server or by a cache), including multiple warnings with the same code | ||
4288 | number. For example, a server might provide the same warning with | ||
4289 | texts in both English and Basque. | ||
4290 | |||
4291 | When multiple warnings are attached to a response, it might not be | ||
4292 | practical or reasonable to display all of them to the user. This | ||
4293 | version of HTTP does not specify strict priority rules for deciding | ||
4294 | which warnings to display and in what order, but does suggest some | ||
4295 | heuristics. | ||
4296 | |||
4297 | 13.1.3 Cache-control Mechanisms | ||
4298 | |||
4299 | The basic cache mechanisms in HTTP/1.1 (server-specified expiration | ||
4300 | times and validators) are implicit directives to caches. In some | ||
4301 | cases, a server or client might need to provide explicit directives | ||
4302 | to the HTTP caches. We use the Cache-Control header for this purpose. | ||
4303 | |||
4304 | The Cache-Control header allows a client or server to transmit a | ||
4305 | variety of directives in either requests or responses. These | ||
4306 | directives typically override the default caching algorithms. As a | ||
4307 | general rule, if there is any apparent conflict between header | ||
4308 | values, the most restrictive interpretation is applied (that is, the | ||
4309 | one that is most likely to preserve semantic transparency). However, | ||
4310 | |||
4311 | |||
4312 | |||
4313 | |||
4314 | Fielding, et al. Standards Track [Page 77] | ||
4315 | |||
4316 | RFC 2616 HTTP/1.1 June 1999 | ||
4317 | |||
4318 | |||
4319 | in some cases, cache-control directives are explicitly specified as | ||
4320 | weakening the approximation of semantic transparency (for example, | ||
4321 | "max-stale" or "public"). | ||
4322 | |||
4323 | The cache-control directives are described in detail in section 14.9. | ||
4324 | |||
4325 | 13.1.4 Explicit User Agent Warnings | ||
4326 | |||
4327 | Many user agents make it possible for users to override the basic | ||
4328 | caching mechanisms. For example, the user agent might allow the user | ||
4329 | to specify that cached entities (even explicitly stale ones) are | ||
4330 | never validated. Or the user agent might habitually add "Cache- | ||
4331 | Control: max-stale=3600" to every request. The user agent SHOULD NOT | ||
4332 | default to either non-transparent behavior, or behavior that results | ||
4333 | in abnormally ineffective caching, but MAY be explicitly configured | ||
4334 | to do so by an explicit action of the user. | ||
4335 | |||
4336 | If the user has overridden the basic caching mechanisms, the user | ||
4337 | agent SHOULD explicitly indicate to the user whenever this results in | ||
4338 | the display of information that might not meet the server's | ||
4339 | transparency requirements (in particular, if the displayed entity is | ||
4340 | known to be stale). Since the protocol normally allows the user agent | ||
4341 | to determine if responses are stale or not, this indication need only | ||
4342 | be displayed when this actually happens. The indication need not be a | ||
4343 | dialog box; it could be an icon (for example, a picture of a rotting | ||
4344 | fish) or some other indicator. | ||
4345 | |||
4346 | If the user has overridden the caching mechanisms in a way that would | ||
4347 | abnormally reduce the effectiveness of caches, the user agent SHOULD | ||
4348 | continually indicate this state to the user (for example, by a | ||
4349 | display of a picture of currency in flames) so that the user does not | ||
4350 | inadvertently consume excess resources or suffer from excessive | ||
4351 | latency. | ||
4352 | |||
4353 | 13.1.5 Exceptions to the Rules and Warnings | ||
4354 | |||
4355 | In some cases, the operator of a cache MAY choose to configure it to | ||
4356 | return stale responses even when not requested by clients. This | ||
4357 | decision ought not be made lightly, but may be necessary for reasons | ||
4358 | of availability or performance, especially when the cache is poorly | ||
4359 | connected to the origin server. Whenever a cache returns a stale | ||
4360 | response, it MUST mark it as such (using a Warning header) enabling | ||
4361 | the client software to alert the user that there might be a potential | ||
4362 | problem. | ||
4363 | |||
4364 | |||
4365 | |||
4366 | |||
4367 | |||
4368 | |||
4369 | |||
4370 | Fielding, et al. Standards Track [Page 78] | ||
4371 | |||
4372 | RFC 2616 HTTP/1.1 June 1999 | ||
4373 | |||
4374 | |||
4375 | It also allows the user agent to take steps to obtain a first-hand or | ||
4376 | fresh response. For this reason, a cache SHOULD NOT return a stale | ||
4377 | response if the client explicitly requests a first-hand or fresh one, | ||
4378 | unless it is impossible to comply for technical or policy reasons. | ||
4379 | |||
4380 | 13.1.6 Client-controlled Behavior | ||
4381 | |||
4382 | While the origin server (and to a lesser extent, intermediate caches, | ||
4383 | by their contribution to the age of a response) are the primary | ||
4384 | source of expiration information, in some cases the client might need | ||
4385 | to control a cache's decision about whether to return a cached | ||
4386 | response without validating it. Clients do this using several | ||
4387 | directives of the Cache-Control header. | ||
4388 | |||
4389 | A client's request MAY specify the maximum age it is willing to | ||
4390 | accept of an unvalidated response; specifying a value of zero forces | ||
4391 | the cache(s) to revalidate all responses. A client MAY also specify | ||
4392 | the minimum time remaining before a response expires. Both of these | ||
4393 | options increase constraints on the behavior of caches, and so cannot | ||
4394 | further relax the cache's approximation of semantic transparency. | ||
4395 | |||
4396 | A client MAY also specify that it will accept stale responses, up to | ||
4397 | some maximum amount of staleness. This loosens the constraints on the | ||
4398 | caches, and so might violate the origin server's specified | ||
4399 | constraints on semantic transparency, but might be necessary to | ||
4400 | support disconnected operation, or high availability in the face of | ||
4401 | poor connectivity. | ||
4402 | |||
4403 | 13.2 Expiration Model | ||
4404 | |||
4405 | 13.2.1 Server-Specified Expiration | ||
4406 | |||
4407 | HTTP caching works best when caches can entirely avoid making | ||
4408 | requests to the origin server. The primary mechanism for avoiding | ||
4409 | requests is for an origin server to provide an explicit expiration | ||
4410 | time in the future, indicating that a response MAY be used to satisfy | ||
4411 | subsequent requests. In other words, a cache can return a fresh | ||
4412 | response without first contacting the server. | ||
4413 | |||
4414 | Our expectation is that servers will assign future explicit | ||
4415 | expiration times to responses in the belief that the entity is not | ||
4416 | likely to change, in a semantically significant way, before the | ||
4417 | expiration time is reached. This normally preserves semantic | ||
4418 | transparency, as long as the server's expiration times are carefully | ||
4419 | chosen. | ||
4420 | |||
4421 | |||
4422 | |||
4423 | |||
4424 | |||
4425 | |||
4426 | Fielding, et al. Standards Track [Page 79] | ||
4427 | |||
4428 | RFC 2616 HTTP/1.1 June 1999 | ||
4429 | |||
4430 | |||
4431 | The expiration mechanism applies only to responses taken from a cache | ||
4432 | and not to first-hand responses forwarded immediately to the | ||
4433 | requesting client. | ||
4434 | |||
4435 | If an origin server wishes to force a semantically transparent cache | ||
4436 | to validate every request, it MAY assign an explicit expiration time | ||
4437 | in the past. This means that the response is always stale, and so the | ||
4438 | cache SHOULD validate it before using it for subsequent requests. See | ||
4439 | section 14.9.4 for a more restrictive way to force revalidation. | ||
4440 | |||
4441 | If an origin server wishes to force any HTTP/1.1 cache, no matter how | ||
4442 | it is configured, to validate every request, it SHOULD use the "must- | ||
4443 | revalidate" cache-control directive (see section 14.9). | ||
4444 | |||
4445 | Servers specify explicit expiration times using either the Expires | ||
4446 | header, or the max-age directive of the Cache-Control header. | ||
4447 | |||
4448 | An expiration time cannot be used to force a user agent to refresh | ||
4449 | its display or reload a resource; its semantics apply only to caching | ||
4450 | mechanisms, and such mechanisms need only check a resource's | ||
4451 | expiration status when a new request for that resource is initiated. | ||
4452 | See section 13.13 for an explanation of the difference between caches | ||
4453 | and history mechanisms. | ||
4454 | |||
4455 | 13.2.2 Heuristic Expiration | ||
4456 | |||
4457 | Since origin servers do not always provide explicit expiration times, | ||
4458 | HTTP caches typically assign heuristic expiration times, employing | ||
4459 | algorithms that use other header values (such as the Last-Modified | ||
4460 | time) to estimate a plausible expiration time. The HTTP/1.1 | ||
4461 | specification does not provide specific algorithms, but does impose | ||
4462 | worst-case constraints on their results. Since heuristic expiration | ||
4463 | times might compromise semantic transparency, they ought to used | ||
4464 | cautiously, and we encourage origin servers to provide explicit | ||
4465 | expiration times as much as possible. | ||
4466 | |||
4467 | 13.2.3 Age Calculations | ||
4468 | |||
4469 | In order to know if a cached entry is fresh, a cache needs to know if | ||
4470 | its age exceeds its freshness lifetime. We discuss how to calculate | ||
4471 | the latter in section 13.2.4; this section describes how to calculate | ||
4472 | the age of a response or cache entry. | ||
4473 | |||
4474 | In this discussion, we use the term "now" to mean "the current value | ||
4475 | of the clock at the host performing the calculation." Hosts that use | ||
4476 | HTTP, but especially hosts running origin servers and caches, SHOULD | ||
4477 | use NTP [28] or some similar protocol to synchronize their clocks to | ||
4478 | a globally accurate time standard. | ||
4479 | |||
4480 | |||
4481 | |||
4482 | Fielding, et al. Standards Track [Page 80] | ||
4483 | |||
4484 | RFC 2616 HTTP/1.1 June 1999 | ||
4485 | |||
4486 | |||
4487 | HTTP/1.1 requires origin servers to send a Date header, if possible, | ||
4488 | with every response, giving the time at which the response was | ||
4489 | generated (see section 14.18). We use the term "date_value" to denote | ||
4490 | the value of the Date header, in a form appropriate for arithmetic | ||
4491 | operations. | ||
4492 | |||
4493 | HTTP/1.1 uses the Age response-header to convey the estimated age of | ||
4494 | the response message when obtained from a cache. The Age field value | ||
4495 | is the cache's estimate of the amount of time since the response was | ||
4496 | generated or revalidated by the origin server. | ||
4497 | |||
4498 | In essence, the Age value is the sum of the time that the response | ||
4499 | has been resident in each of the caches along the path from the | ||
4500 | origin server, plus the amount of time it has been in transit along | ||
4501 | network paths. | ||
4502 | |||
4503 | We use the term "age_value" to denote the value of the Age header, in | ||
4504 | a form appropriate for arithmetic operations. | ||
4505 | |||
4506 | A response's age can be calculated in two entirely independent ways: | ||
4507 | |||
4508 | 1. now minus date_value, if the local clock is reasonably well | ||
4509 | synchronized to the origin server's clock. If the result is | ||
4510 | negative, the result is replaced by zero. | ||
4511 | |||
4512 | 2. age_value, if all of the caches along the response path | ||
4513 | implement HTTP/1.1. | ||
4514 | |||
4515 | Given that we have two independent ways to compute the age of a | ||
4516 | response when it is received, we can combine these as | ||
4517 | |||
4518 | corrected_received_age = max(now - date_value, age_value) | ||
4519 | |||
4520 | and as long as we have either nearly synchronized clocks or all- | ||
4521 | HTTP/1.1 paths, one gets a reliable (conservative) result. | ||
4522 | |||
4523 | Because of network-imposed delays, some significant interval might | ||
4524 | pass between the time that a server generates a response and the time | ||
4525 | it is received at the next outbound cache or client. If uncorrected, | ||
4526 | this delay could result in improperly low ages. | ||
4527 | |||
4528 | Because the request that resulted in the returned Age value must have | ||
4529 | been initiated prior to that Age value's generation, we can correct | ||
4530 | for delays imposed by the network by recording the time at which the | ||
4531 | request was initiated. Then, when an Age value is received, it MUST | ||
4532 | be interpreted relative to the time the request was initiated, not | ||
4533 | |||
4534 | |||
4535 | |||
4536 | |||
4537 | |||
4538 | Fielding, et al. Standards Track [Page 81] | ||
4539 | |||
4540 | RFC 2616 HTTP/1.1 June 1999 | ||
4541 | |||
4542 | |||
4543 | the time that the response was received. This algorithm results in | ||
4544 | conservative behavior no matter how much delay is experienced. So, we | ||
4545 | compute: | ||
4546 | |||
4547 | corrected_initial_age = corrected_received_age | ||
4548 | + (now - request_time) | ||
4549 | |||
4550 | where "request_time" is the time (according to the local clock) when | ||
4551 | the request that elicited this response was sent. | ||
4552 | |||
4553 | Summary of age calculation algorithm, when a cache receives a | ||
4554 | response: | ||
4555 | |||
4556 | /* | ||
4557 | * age_value | ||
4558 | * is the value of Age: header received by the cache with | ||
4559 | * this response. | ||
4560 | * date_value | ||
4561 | * is the value of the origin server's Date: header | ||
4562 | * request_time | ||
4563 | * is the (local) time when the cache made the request | ||
4564 | * that resulted in this cached response | ||
4565 | * response_time | ||
4566 | * is the (local) time when the cache received the | ||
4567 | * response | ||
4568 | * now | ||
4569 | * is the current (local) time | ||
4570 | */ | ||
4571 | |||
4572 | apparent_age = max(0, response_time - date_value); | ||
4573 | corrected_received_age = max(apparent_age, age_value); | ||
4574 | response_delay = response_time - request_time; | ||
4575 | corrected_initial_age = corrected_received_age + response_delay; | ||
4576 | resident_time = now - response_time; | ||
4577 | current_age = corrected_initial_age + resident_time; | ||
4578 | |||
4579 | The current_age of a cache entry is calculated by adding the amount | ||
4580 | of time (in seconds) since the cache entry was last validated by the | ||
4581 | origin server to the corrected_initial_age. When a response is | ||
4582 | generated from a cache entry, the cache MUST include a single Age | ||
4583 | header field in the response with a value equal to the cache entry's | ||
4584 | current_age. | ||
4585 | |||
4586 | The presence of an Age header field in a response implies that a | ||
4587 | response is not first-hand. However, the converse is not true, since | ||
4588 | the lack of an Age header field in a response does not imply that the | ||
4589 | |||
4590 | |||
4591 | |||
4592 | |||
4593 | |||
4594 | Fielding, et al. Standards Track [Page 82] | ||
4595 | |||
4596 | RFC 2616 HTTP/1.1 June 1999 | ||
4597 | |||
4598 | |||
4599 | response is first-hand unless all caches along the request path are | ||
4600 | compliant with HTTP/1.1 (i.e., older HTTP caches did not implement | ||
4601 | the Age header field). | ||
4602 | |||
4603 | 13.2.4 Expiration Calculations | ||
4604 | |||
4605 | In order to decide whether a response is fresh or stale, we need to | ||
4606 | compare its freshness lifetime to its age. The age is calculated as | ||
4607 | described in section 13.2.3; this section describes how to calculate | ||
4608 | the freshness lifetime, and to determine if a response has expired. | ||
4609 | In the discussion below, the values can be represented in any form | ||
4610 | appropriate for arithmetic operations. | ||
4611 | |||
4612 | We use the term "expires_value" to denote the value of the Expires | ||
4613 | header. We use the term "max_age_value" to denote an appropriate | ||
4614 | value of the number of seconds carried by the "max-age" directive of | ||
4615 | the Cache-Control header in a response (see section 14.9.3). | ||
4616 | |||
4617 | The max-age directive takes priority over Expires, so if max-age is | ||
4618 | present in a response, the calculation is simply: | ||
4619 | |||
4620 | freshness_lifetime = max_age_value | ||
4621 | |||
4622 | Otherwise, if Expires is present in the response, the calculation is: | ||
4623 | |||
4624 | freshness_lifetime = expires_value - date_value | ||
4625 | |||
4626 | Note that neither of these calculations is vulnerable to clock skew, | ||
4627 | since all of the information comes from the origin server. | ||
4628 | |||
4629 | If none of Expires, Cache-Control: max-age, or Cache-Control: s- | ||
4630 | maxage (see section 14.9.3) appears in the response, and the response | ||
4631 | does not include other restrictions on caching, the cache MAY compute | ||
4632 | a freshness lifetime using a heuristic. The cache MUST attach Warning | ||
4633 | 113 to any response whose age is more than 24 hours if such warning | ||
4634 | has not already been added. | ||
4635 | |||
4636 | Also, if the response does have a Last-Modified time, the heuristic | ||
4637 | expiration value SHOULD be no more than some fraction of the interval | ||
4638 | since that time. A typical setting of this fraction might be 10%. | ||
4639 | |||
4640 | The calculation to determine if a response has expired is quite | ||
4641 | simple: | ||
4642 | |||
4643 | response_is_fresh = (freshness_lifetime > current_age) | ||
4644 | |||
4645 | |||
4646 | |||
4647 | |||
4648 | |||
4649 | |||
4650 | Fielding, et al. Standards Track [Page 83] | ||
4651 | |||
4652 | RFC 2616 HTTP/1.1 June 1999 | ||
4653 | |||
4654 | |||
4655 | 13.2.5 Disambiguating Expiration Values | ||
4656 | |||
4657 | Because expiration values are assigned optimistically, it is possible | ||
4658 | for two caches to contain fresh values for the same resource that are | ||
4659 | different. | ||
4660 | |||
4661 | If a client performing a retrieval receives a non-first-hand response | ||
4662 | for a request that was already fresh in its own cache, and the Date | ||
4663 | header in its existing cache entry is newer than the Date on the new | ||
4664 | response, then the client MAY ignore the response. If so, it MAY | ||
4665 | retry the request with a "Cache-Control: max-age=0" directive (see | ||
4666 | section 14.9), to force a check with the origin server. | ||
4667 | |||
4668 | If a cache has two fresh responses for the same representation with | ||
4669 | different validators, it MUST use the one with the more recent Date | ||
4670 | header. This situation might arise because the cache is pooling | ||
4671 | responses from other caches, or because a client has asked for a | ||
4672 | reload or a revalidation of an apparently fresh cache entry. | ||
4673 | |||
4674 | 13.2.6 Disambiguating Multiple Responses | ||
4675 | |||
4676 | Because a client might be receiving responses via multiple paths, so | ||
4677 | that some responses flow through one set of caches and other | ||
4678 | responses flow through a different set of caches, a client might | ||
4679 | receive responses in an order different from that in which the origin | ||
4680 | server sent them. We would like the client to use the most recently | ||
4681 | generated response, even if older responses are still apparently | ||
4682 | fresh. | ||
4683 | |||
4684 | Neither the entity tag nor the expiration value can impose an | ||
4685 | ordering on responses, since it is possible that a later response | ||
4686 | intentionally carries an earlier expiration time. The Date values are | ||
4687 | ordered to a granularity of one second. | ||
4688 | |||
4689 | When a client tries to revalidate a cache entry, and the response it | ||
4690 | receives contains a Date header that appears to be older than the one | ||
4691 | for the existing entry, then the client SHOULD repeat the request | ||
4692 | unconditionally, and include | ||
4693 | |||
4694 | Cache-Control: max-age=0 | ||
4695 | |||
4696 | to force any intermediate caches to validate their copies directly | ||
4697 | with the origin server, or | ||
4698 | |||
4699 | Cache-Control: no-cache | ||
4700 | |||
4701 | to force any intermediate caches to obtain a new copy from the origin | ||
4702 | server. | ||
4703 | |||
4704 | |||
4705 | |||
4706 | Fielding, et al. Standards Track [Page 84] | ||
4707 | |||
4708 | RFC 2616 HTTP/1.1 June 1999 | ||
4709 | |||
4710 | |||
4711 | If the Date values are equal, then the client MAY use either response | ||
4712 | (or MAY, if it is being extremely prudent, request a new response). | ||
4713 | Servers MUST NOT depend on clients being able to choose | ||
4714 | deterministically between responses generated during the same second, | ||
4715 | if their expiration times overlap. | ||
4716 | |||
4717 | 13.3 Validation Model | ||
4718 | |||
4719 | When a cache has a stale entry that it would like to use as a | ||
4720 | response to a client's request, it first has to check with the origin | ||
4721 | server (or possibly an intermediate cache with a fresh response) to | ||
4722 | see if its cached entry is still usable. We call this "validating" | ||
4723 | the cache entry. Since we do not want to have to pay the overhead of | ||
4724 | retransmitting the full response if the cached entry is good, and we | ||
4725 | do not want to pay the overhead of an extra round trip if the cached | ||
4726 | entry is invalid, the HTTP/1.1 protocol supports the use of | ||
4727 | conditional methods. | ||
4728 | |||
4729 | The key protocol features for supporting conditional methods are | ||
4730 | those concerned with "cache validators." When an origin server | ||
4731 | generates a full response, it attaches some sort of validator to it, | ||
4732 | which is kept with the cache entry. When a client (user agent or | ||
4733 | proxy cache) makes a conditional request for a resource for which it | ||
4734 | has a cache entry, it includes the associated validator in the | ||
4735 | request. | ||
4736 | |||
4737 | The server then checks that validator against the current validator | ||
4738 | for the entity, and, if they match (see section 13.3.3), it responds | ||
4739 | with a special status code (usually, 304 (Not Modified)) and no | ||
4740 | entity-body. Otherwise, it returns a full response (including | ||
4741 | entity-body). Thus, we avoid transmitting the full response if the | ||
4742 | validator matches, and we avoid an extra round trip if it does not | ||
4743 | match. | ||
4744 | |||
4745 | In HTTP/1.1, a conditional request looks exactly the same as a normal | ||
4746 | request for the same resource, except that it carries a special | ||
4747 | header (which includes the validator) that implicitly turns the | ||
4748 | method (usually, GET) into a conditional. | ||
4749 | |||
4750 | The protocol includes both positive and negative senses of cache- | ||
4751 | validating conditions. That is, it is possible to request either that | ||
4752 | a method be performed if and only if a validator matches or if and | ||
4753 | only if no validators match. | ||
4754 | |||
4755 | |||
4756 | |||
4757 | |||
4758 | |||
4759 | |||
4760 | |||
4761 | |||
4762 | Fielding, et al. Standards Track [Page 85] | ||
4763 | |||
4764 | RFC 2616 HTTP/1.1 June 1999 | ||
4765 | |||
4766 | |||
4767 | Note: a response that lacks a validator may still be cached, and | ||
4768 | served from cache until it expires, unless this is explicitly | ||
4769 | prohibited by a cache-control directive. However, a cache cannot | ||
4770 | do a conditional retrieval if it does not have a validator for the | ||
4771 | entity, which means it will not be refreshable after it expires. | ||
4772 | |||
4773 | 13.3.1 Last-Modified Dates | ||
4774 | |||
4775 | The Last-Modified entity-header field value is often used as a cache | ||
4776 | validator. In simple terms, a cache entry is considered to be valid | ||
4777 | if the entity has not been modified since the Last-Modified value. | ||
4778 | |||
4779 | 13.3.2 Entity Tag Cache Validators | ||
4780 | |||
4781 | The ETag response-header field value, an entity tag, provides for an | ||
4782 | "opaque" cache validator. This might allow more reliable validation | ||
4783 | in situations where it is inconvenient to store modification dates, | ||
4784 | where the one-second resolution of HTTP date values is not | ||
4785 | sufficient, or where the origin server wishes to avoid certain | ||
4786 | paradoxes that might arise from the use of modification dates. | ||
4787 | |||
4788 | Entity Tags are described in section 3.11. The headers used with | ||
4789 | entity tags are described in sections 14.19, 14.24, 14.26 and 14.44. | ||
4790 | |||
4791 | 13.3.3 Weak and Strong Validators | ||
4792 | |||
4793 | Since both origin servers and caches will compare two validators to | ||
4794 | decide if they represent the same or different entities, one normally | ||
4795 | would expect that if the entity (the entity-body or any entity- | ||
4796 | headers) changes in any way, then the associated validator would | ||
4797 | change as well. If this is true, then we call this validator a | ||
4798 | "strong validator." | ||
4799 | |||
4800 | However, there might be cases when a server prefers to change the | ||
4801 | validator only on semantically significant changes, and not when | ||
4802 | insignificant aspects of the entity change. A validator that does not | ||
4803 | always change when the resource changes is a "weak validator." | ||
4804 | |||
4805 | Entity tags are normally "strong validators," but the protocol | ||
4806 | provides a mechanism to tag an entity tag as "weak." One can think of | ||
4807 | a strong validator as one that changes whenever the bits of an entity | ||
4808 | changes, while a weak value changes whenever the meaning of an entity | ||
4809 | changes. Alternatively, one can think of a strong validator as part | ||
4810 | of an identifier for a specific entity, while a weak validator is | ||
4811 | part of an identifier for a set of semantically equivalent entities. | ||
4812 | |||
4813 | Note: One example of a strong validator is an integer that is | ||
4814 | incremented in stable storage every time an entity is changed. | ||
4815 | |||
4816 | |||
4817 | |||
4818 | Fielding, et al. Standards Track [Page 86] | ||
4819 | |||
4820 | RFC 2616 HTTP/1.1 June 1999 | ||
4821 | |||
4822 | |||
4823 | An entity's modification time, if represented with one-second | ||
4824 | resolution, could be a weak validator, since it is possible that | ||
4825 | the resource might be modified twice during a single second. | ||
4826 | |||
4827 | Support for weak validators is optional. However, weak validators | ||
4828 | allow for more efficient caching of equivalent objects; for | ||
4829 | example, a hit counter on a site is probably good enough if it is | ||
4830 | updated every few days or weeks, and any value during that period | ||
4831 | is likely "good enough" to be equivalent. | ||
4832 | |||
4833 | A "use" of a validator is either when a client generates a request | ||
4834 | and includes the validator in a validating header field, or when a | ||
4835 | server compares two validators. | ||
4836 | |||
4837 | Strong validators are usable in any context. Weak validators are only | ||
4838 | usable in contexts that do not depend on exact equality of an entity. | ||
4839 | For example, either kind is usable for a conditional GET of a full | ||
4840 | entity. However, only a strong validator is usable for a sub-range | ||
4841 | retrieval, since otherwise the client might end up with an internally | ||
4842 | inconsistent entity. | ||
4843 | |||
4844 | Clients MAY issue simple (non-subrange) GET requests with either weak | ||
4845 | validators or strong validators. Clients MUST NOT use weak validators | ||
4846 | in other forms of request. | ||
4847 | |||
4848 | The only function that the HTTP/1.1 protocol defines on validators is | ||
4849 | comparison. There are two validator comparison functions, depending | ||
4850 | on whether the comparison context allows the use of weak validators | ||
4851 | or not: | ||
4852 | |||
4853 | - The strong comparison function: in order to be considered equal, | ||
4854 | both validators MUST be identical in every way, and both MUST | ||
4855 | NOT be weak. | ||
4856 | |||
4857 | - The weak comparison function: in order to be considered equal, | ||
4858 | both validators MUST be identical in every way, but either or | ||
4859 | both of them MAY be tagged as "weak" without affecting the | ||
4860 | result. | ||
4861 | |||
4862 | An entity tag is strong unless it is explicitly tagged as weak. | ||
4863 | Section 3.11 gives the syntax for entity tags. | ||
4864 | |||
4865 | A Last-Modified time, when used as a validator in a request, is | ||
4866 | implicitly weak unless it is possible to deduce that it is strong, | ||
4867 | using the following rules: | ||
4868 | |||
4869 | - The validator is being compared by an origin server to the | ||
4870 | actual current validator for the entity and, | ||
4871 | |||
4872 | |||
4873 | |||
4874 | Fielding, et al. Standards Track [Page 87] | ||
4875 | |||
4876 | RFC 2616 HTTP/1.1 June 1999 | ||
4877 | |||
4878 | |||
4879 | - That origin server reliably knows that the associated entity did | ||
4880 | not change twice during the second covered by the presented | ||
4881 | validator. | ||
4882 | |||
4883 | or | ||
4884 | |||
4885 | - The validator is about to be used by a client in an If- | ||
4886 | Modified-Since or If-Unmodified-Since header, because the client | ||
4887 | has a cache entry for the associated entity, and | ||
4888 | |||
4889 | - That cache entry includes a Date value, which gives the time | ||
4890 | when the origin server sent the original response, and | ||
4891 | |||
4892 | - The presented Last-Modified time is at least 60 seconds before | ||
4893 | the Date value. | ||
4894 | |||
4895 | or | ||
4896 | |||
4897 | - The validator is being compared by an intermediate cache to the | ||
4898 | validator stored in its cache entry for the entity, and | ||
4899 | |||
4900 | - That cache entry includes a Date value, which gives the time | ||
4901 | when the origin server sent the original response, and | ||
4902 | |||
4903 | - The presented Last-Modified time is at least 60 seconds before | ||
4904 | the Date value. | ||
4905 | |||
4906 | This method relies on the fact that if two different responses were | ||
4907 | sent by the origin server during the same second, but both had the | ||
4908 | same Last-Modified time, then at least one of those responses would | ||
4909 | have a Date value equal to its Last-Modified time. The arbitrary 60- | ||
4910 | second limit guards against the possibility that the Date and Last- | ||
4911 | Modified values are generated from different clocks, or at somewhat | ||
4912 | different times during the preparation of the response. An | ||
4913 | implementation MAY use a value larger than 60 seconds, if it is | ||
4914 | believed that 60 seconds is too short. | ||
4915 | |||
4916 | If a client wishes to perform a sub-range retrieval on a value for | ||
4917 | which it has only a Last-Modified time and no opaque validator, it | ||
4918 | MAY do this only if the Last-Modified time is strong in the sense | ||
4919 | described here. | ||
4920 | |||
4921 | A cache or origin server receiving a conditional request, other than | ||
4922 | a full-body GET request, MUST use the strong comparison function to | ||
4923 | evaluate the condition. | ||
4924 | |||
4925 | These rules allow HTTP/1.1 caches and clients to safely perform sub- | ||
4926 | range retrievals on values that have been obtained from HTTP/1.0 | ||
4927 | |||
4928 | |||
4929 | |||
4930 | Fielding, et al. Standards Track [Page 88] | ||
4931 | |||
4932 | RFC 2616 HTTP/1.1 June 1999 | ||
4933 | |||
4934 | |||
4935 | servers. | ||
4936 | |||
4937 | 13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates | ||
4938 | |||
4939 | We adopt a set of rules and recommendations for origin servers, | ||
4940 | clients, and caches regarding when various validator types ought to | ||
4941 | be used, and for what purposes. | ||
4942 | |||
4943 | HTTP/1.1 origin servers: | ||
4944 | |||
4945 | - SHOULD send an entity tag validator unless it is not feasible to | ||
4946 | generate one. | ||
4947 | |||
4948 | - MAY send a weak entity tag instead of a strong entity tag, if | ||
4949 | performance considerations support the use of weak entity tags, | ||
4950 | or if it is unfeasible to send a strong entity tag. | ||
4951 | |||
4952 | - SHOULD send a Last-Modified value if it is feasible to send one, | ||
4953 | unless the risk of a breakdown in semantic transparency that | ||
4954 | could result from using this date in an If-Modified-Since header | ||
4955 | would lead to serious problems. | ||
4956 | |||
4957 | In other words, the preferred behavior for an HTTP/1.1 origin server | ||
4958 | is to send both a strong entity tag and a Last-Modified value. | ||
4959 | |||
4960 | In order to be legal, a strong entity tag MUST change whenever the | ||
4961 | associated entity value changes in any way. A weak entity tag SHOULD | ||
4962 | change whenever the associated entity changes in a semantically | ||
4963 | significant way. | ||
4964 | |||
4965 | Note: in order to provide semantically transparent caching, an | ||
4966 | origin server must avoid reusing a specific strong entity tag | ||
4967 | value for two different entities, or reusing a specific weak | ||
4968 | entity tag value for two semantically different entities. Cache | ||
4969 | entries might persist for arbitrarily long periods, regardless of | ||
4970 | expiration times, so it might be inappropriate to expect that a | ||
4971 | cache will never again attempt to validate an entry using a | ||
4972 | validator that it obtained at some point in the past. | ||
4973 | |||
4974 | HTTP/1.1 clients: | ||
4975 | |||
4976 | - If an entity tag has been provided by the origin server, MUST | ||
4977 | use that entity tag in any cache-conditional request (using If- | ||
4978 | Match or If-None-Match). | ||
4979 | |||
4980 | - If only a Last-Modified value has been provided by the origin | ||
4981 | server, SHOULD use that value in non-subrange cache-conditional | ||
4982 | requests (using If-Modified-Since). | ||
4983 | |||
4984 | |||
4985 | |||
4986 | Fielding, et al. Standards Track [Page 89] | ||
4987 | |||
4988 | RFC 2616 HTTP/1.1 June 1999 | ||
4989 | |||
4990 | |||
4991 | - If only a Last-Modified value has been provided by an HTTP/1.0 | ||
4992 | origin server, MAY use that value in subrange cache-conditional | ||
4993 | requests (using If-Unmodified-Since:). The user agent SHOULD | ||
4994 | provide a way to disable this, in case of difficulty. | ||
4995 | |||
4996 | - If both an entity tag and a Last-Modified value have been | ||
4997 | provided by the origin server, SHOULD use both validators in | ||
4998 | cache-conditional requests. This allows both HTTP/1.0 and | ||
4999 | HTTP/1.1 caches to respond appropriately. | ||
5000 | |||
5001 | An HTTP/1.1 origin server, upon receiving a conditional request that | ||
5002 | includes both a Last-Modified date (e.g., in an If-Modified-Since or | ||
5003 | If-Unmodified-Since header field) and one or more entity tags (e.g., | ||
5004 | in an If-Match, If-None-Match, or If-Range header field) as cache | ||
5005 | validators, MUST NOT return a response status of 304 (Not Modified) | ||
5006 | unless doing so is consistent with all of the conditional header | ||
5007 | fields in the request. | ||
5008 | |||
5009 | An HTTP/1.1 caching proxy, upon receiving a conditional request that | ||
5010 | includes both a Last-Modified date and one or more entity tags as | ||
5011 | cache validators, MUST NOT return a locally cached response to the | ||
5012 | client unless that cached response is consistent with all of the | ||
5013 | conditional header fields in the request. | ||
5014 | |||
5015 | Note: The general principle behind these rules is that HTTP/1.1 | ||
5016 | servers and clients should transmit as much non-redundant | ||
5017 | information as is available in their responses and requests. | ||
5018 | HTTP/1.1 systems receiving this information will make the most | ||
5019 | conservative assumptions about the validators they receive. | ||
5020 | |||
5021 | HTTP/1.0 clients and caches will ignore entity tags. Generally, | ||
5022 | last-modified values received or used by these systems will | ||
5023 | support transparent and efficient caching, and so HTTP/1.1 origin | ||
5024 | servers should provide Last-Modified values. In those rare cases | ||
5025 | where the use of a Last-Modified value as a validator by an | ||
5026 | HTTP/1.0 system could result in a serious problem, then HTTP/1.1 | ||
5027 | origin servers should not provide one. | ||
5028 | |||
5029 | 13.3.5 Non-validating Conditionals | ||
5030 | |||
5031 | The principle behind entity tags is that only the service author | ||
5032 | knows the semantics of a resource well enough to select an | ||
5033 | appropriate cache validation mechanism, and the specification of any | ||
5034 | validator comparison function more complex than byte-equality would | ||
5035 | open up a can of worms. Thus, comparisons of any other headers | ||
5036 | (except Last-Modified, for compatibility with HTTP/1.0) are never | ||
5037 | used for purposes of validating a cache entry. | ||
5038 | |||
5039 | |||
5040 | |||
5041 | |||
5042 | Fielding, et al. Standards Track [Page 90] | ||
5043 | |||
5044 | RFC 2616 HTTP/1.1 June 1999 | ||
5045 | |||
5046 | |||
5047 | 13.4 Response Cacheability | ||
5048 | |||
5049 | Unless specifically constrained by a cache-control (section 14.9) | ||
5050 | directive, a caching system MAY always store a successful response | ||
5051 | (see section 13.8) as a cache entry, MAY return it without validation | ||
5052 | if it is fresh, and MAY return it after successful validation. If | ||
5053 | there is neither a cache validator nor an explicit expiration time | ||
5054 | associated with a response, we do not expect it to be cached, but | ||
5055 | certain caches MAY violate this expectation (for example, when little | ||
5056 | or no network connectivity is available). A client can usually detect | ||
5057 | that such a response was taken from a cache by comparing the Date | ||
5058 | header to the current time. | ||
5059 | |||
5060 | Note: some HTTP/1.0 caches are known to violate this expectation | ||
5061 | without providing any Warning. | ||
5062 | |||
5063 | However, in some cases it might be inappropriate for a cache to | ||
5064 | retain an entity, or to return it in response to a subsequent | ||
5065 | request. This might be because absolute semantic transparency is | ||
5066 | deemed necessary by the service author, or because of security or | ||
5067 | privacy considerations. Certain cache-control directives are | ||
5068 | therefore provided so that the server can indicate that certain | ||
5069 | resource entities, or portions thereof, are not to be cached | ||
5070 | regardless of other considerations. | ||
5071 | |||
5072 | Note that section 14.8 normally prevents a shared cache from saving | ||
5073 | and returning a response to a previous request if that request | ||
5074 | included an Authorization header. | ||
5075 | |||
5076 | A response received with a status code of 200, 203, 206, 300, 301 or | ||
5077 | 410 MAY be stored by a cache and used in reply to a subsequent | ||
5078 | request, subject to the expiration mechanism, unless a cache-control | ||
5079 | directive prohibits caching. However, a cache that does not support | ||
5080 | the Range and Content-Range headers MUST NOT cache 206 (Partial | ||
5081 | Content) responses. | ||
5082 | |||
5083 | A response received with any other status code (e.g. status codes 302 | ||
5084 | and 307) MUST NOT be returned in a reply to a subsequent request | ||
5085 | unless there are cache-control directives or another header(s) that | ||
5086 | explicitly allow it. For example, these include the following: an | ||
5087 | Expires header (section 14.21); a "max-age", "s-maxage", "must- | ||
5088 | revalidate", "proxy-revalidate", "public" or "private" cache-control | ||
5089 | directive (section 14.9). | ||
5090 | |||
5091 | |||
5092 | |||
5093 | |||
5094 | |||
5095 | |||
5096 | |||
5097 | |||
5098 | Fielding, et al. Standards Track [Page 91] | ||
5099 | |||
5100 | RFC 2616 HTTP/1.1 June 1999 | ||
5101 | |||
5102 | |||
5103 | 13.5 Constructing Responses From Caches | ||
5104 | |||
5105 | The purpose of an HTTP cache is to store information received in | ||
5106 | response to requests for use in responding to future requests. In | ||
5107 | many cases, a cache simply returns the appropriate parts of a | ||
5108 | response to the requester. However, if the cache holds a cache entry | ||
5109 | based on a previous response, it might have to combine parts of a new | ||
5110 | response with what is held in the cache entry. | ||
5111 | |||
5112 | 13.5.1 End-to-end and Hop-by-hop Headers | ||
5113 | |||
5114 | For the purpose of defining the behavior of caches and non-caching | ||
5115 | proxies, we divide HTTP headers into two categories: | ||
5116 | |||
5117 | - End-to-end headers, which are transmitted to the ultimate | ||
5118 | recipient of a request or response. End-to-end headers in | ||
5119 | responses MUST be stored as part of a cache entry and MUST be | ||
5120 | transmitted in any response formed from a cache entry. | ||
5121 | |||
5122 | - Hop-by-hop headers, which are meaningful only for a single | ||
5123 | transport-level connection, and are not stored by caches or | ||
5124 | forwarded by proxies. | ||
5125 | |||
5126 | The following HTTP/1.1 headers are hop-by-hop headers: | ||
5127 | |||
5128 | - Connection | ||
5129 | - Keep-Alive | ||
5130 | - Proxy-Authenticate | ||
5131 | - Proxy-Authorization | ||
5132 | - TE | ||
5133 | - Trailers | ||
5134 | - Transfer-Encoding | ||
5135 | - Upgrade | ||
5136 | |||
5137 | All other headers defined by HTTP/1.1 are end-to-end headers. | ||
5138 | |||
5139 | Other hop-by-hop headers MUST be listed in a Connection header, | ||
5140 | (section 14.10) to be introduced into HTTP/1.1 (or later). | ||
5141 | |||
5142 | 13.5.2 Non-modifiable Headers | ||
5143 | |||
5144 | Some features of the HTTP/1.1 protocol, such as Digest | ||
5145 | Authentication, depend on the value of certain end-to-end headers. A | ||
5146 | transparent proxy SHOULD NOT modify an end-to-end header unless the | ||
5147 | definition of that header requires or specifically allows that. | ||
5148 | |||
5149 | |||
5150 | |||
5151 | |||
5152 | |||
5153 | |||
5154 | Fielding, et al. Standards Track [Page 92] | ||
5155 | |||
5156 | RFC 2616 HTTP/1.1 June 1999 | ||
5157 | |||
5158 | |||
5159 | A transparent proxy MUST NOT modify any of the following fields in a | ||
5160 | request or response, and it MUST NOT add any of these fields if not | ||
5161 | already present: | ||
5162 | |||
5163 | - Content-Location | ||
5164 | |||
5165 | - Content-MD5 | ||
5166 | |||
5167 | - ETag | ||
5168 | |||
5169 | - Last-Modified | ||
5170 | |||
5171 | A transparent proxy MUST NOT modify any of the following fields in a | ||
5172 | response: | ||
5173 | |||
5174 | - Expires | ||
5175 | |||
5176 | but it MAY add any of these fields if not already present. If an | ||
5177 | Expires header is added, it MUST be given a field-value identical to | ||
5178 | that of the Date header in that response. | ||
5179 | |||
5180 | A proxy MUST NOT modify or add any of the following fields in a | ||
5181 | message that contains the no-transform cache-control directive, or in | ||
5182 | any request: | ||
5183 | |||
5184 | - Content-Encoding | ||
5185 | |||
5186 | - Content-Range | ||
5187 | |||
5188 | - Content-Type | ||
5189 | |||
5190 | A non-transparent proxy MAY modify or add these fields to a message | ||
5191 | that does not include no-transform, but if it does so, it MUST add a | ||
5192 | Warning 214 (Transformation applied) if one does not already appear | ||
5193 | in the message (see section 14.46). | ||
5194 | |||
5195 | Warning: unnecessary modification of end-to-end headers might | ||
5196 | cause authentication failures if stronger authentication | ||
5197 | mechanisms are introduced in later versions of HTTP. Such | ||
5198 | authentication mechanisms MAY rely on the values of header fields | ||
5199 | not listed here. | ||
5200 | |||
5201 | The Content-Length field of a request or response is added or deleted | ||
5202 | according to the rules in section 4.4. A transparent proxy MUST | ||
5203 | preserve the entity-length (section 7.2.2) of the entity-body, | ||
5204 | although it MAY change the transfer-length (section 4.4). | ||
5205 | |||
5206 | |||
5207 | |||
5208 | |||
5209 | |||
5210 | Fielding, et al. Standards Track [Page 93] | ||
5211 | |||
5212 | RFC 2616 HTTP/1.1 June 1999 | ||
5213 | |||
5214 | |||
5215 | 13.5.3 Combining Headers | ||
5216 | |||
5217 | When a cache makes a validating request to a server, and the server | ||
5218 | provides a 304 (Not Modified) response or a 206 (Partial Content) | ||
5219 | response, the cache then constructs a response to send to the | ||
5220 | requesting client. | ||
5221 | |||
5222 | If the status code is 304 (Not Modified), the cache uses the entity- | ||
5223 | body stored in the cache entry as the entity-body of this outgoing | ||
5224 | response. If the status code is 206 (Partial Content) and the ETag or | ||
5225 | Last-Modified headers match exactly, the cache MAY combine the | ||
5226 | contents stored in the cache entry with the new contents received in | ||
5227 | the response and use the result as the entity-body of this outgoing | ||
5228 | response, (see 13.5.4). | ||
5229 | |||
5230 | The end-to-end headers stored in the cache entry are used for the | ||
5231 | constructed response, except that | ||
5232 | |||
5233 | - any stored Warning headers with warn-code 1xx (see section | ||
5234 | 14.46) MUST be deleted from the cache entry and the forwarded | ||
5235 | response. | ||
5236 | |||
5237 | - any stored Warning headers with warn-code 2xx MUST be retained | ||
5238 | in the cache entry and the forwarded response. | ||
5239 | |||
5240 | - any end-to-end headers provided in the 304 or 206 response MUST | ||
5241 | replace the corresponding headers from the cache entry. | ||
5242 | |||
5243 | Unless the cache decides to remove the cache entry, it MUST also | ||
5244 | replace the end-to-end headers stored with the cache entry with | ||
5245 | corresponding headers received in the incoming response, except for | ||
5246 | Warning headers as described immediately above. If a header field- | ||
5247 | name in the incoming response matches more than one header in the | ||
5248 | cache entry, all such old headers MUST be replaced. | ||
5249 | |||
5250 | In other words, the set of end-to-end headers received in the | ||
5251 | incoming response overrides all corresponding end-to-end headers | ||
5252 | stored with the cache entry (except for stored Warning headers with | ||
5253 | warn-code 1xx, which are deleted even if not overridden). | ||
5254 | |||
5255 | Note: this rule allows an origin server to use a 304 (Not | ||
5256 | Modified) or a 206 (Partial Content) response to update any header | ||
5257 | associated with a previous response for the same entity or sub- | ||
5258 | ranges thereof, although it might not always be meaningful or | ||
5259 | correct to do so. This rule does not allow an origin server to use | ||
5260 | a 304 (Not Modified) or a 206 (Partial Content) response to | ||
5261 | entirely delete a header that it had provided with a previous | ||
5262 | response. | ||
5263 | |||
5264 | |||
5265 | |||
5266 | Fielding, et al. Standards Track [Page 94] | ||
5267 | |||
5268 | RFC 2616 HTTP/1.1 June 1999 | ||
5269 | |||
5270 | |||
5271 | 13.5.4 Combining Byte Ranges | ||
5272 | |||
5273 | A response might transfer only a subrange of the bytes of an entity- | ||
5274 | body, either because the request included one or more Range | ||
5275 | specifications, or because a connection was broken prematurely. After | ||
5276 | several such transfers, a cache might have received several ranges of | ||
5277 | the same entity-body. | ||
5278 | |||
5279 | If a cache has a stored non-empty set of subranges for an entity, and | ||
5280 | an incoming response transfers another subrange, the cache MAY | ||
5281 | combine the new subrange with the existing set if both the following | ||
5282 | conditions are met: | ||
5283 | |||
5284 | - Both the incoming response and the cache entry have a cache | ||
5285 | validator. | ||
5286 | |||
5287 | - The two cache validators match using the strong comparison | ||
5288 | function (see section 13.3.3). | ||
5289 | |||
5290 | If either requirement is not met, the cache MUST use only the most | ||
5291 | recent partial response (based on the Date values transmitted with | ||
5292 | every response, and using the incoming response if these values are | ||
5293 | equal or missing), and MUST discard the other partial information. | ||
5294 | |||
5295 | 13.6 Caching Negotiated Responses | ||
5296 | |||
5297 | Use of server-driven content negotiation (section 12.1), as indicated | ||
5298 | by the presence of a Vary header field in a response, alters the | ||
5299 | conditions and procedure by which a cache can use the response for | ||
5300 | subsequent requests. See section 14.44 for use of the Vary header | ||
5301 | field by servers. | ||
5302 | |||
5303 | A server SHOULD use the Vary header field to inform a cache of what | ||
5304 | request-header fields were used to select among multiple | ||
5305 | representations of a cacheable response subject to server-driven | ||
5306 | negotiation. The set of header fields named by the Vary field value | ||
5307 | is known as the "selecting" request-headers. | ||
5308 | |||
5309 | When the cache receives a subsequent request whose Request-URI | ||
5310 | specifies one or more cache entries including a Vary header field, | ||
5311 | the cache MUST NOT use such a cache entry to construct a response to | ||
5312 | the new request unless all of the selecting request-headers present | ||
5313 | in the new request match the corresponding stored request-headers in | ||
5314 | the original request. | ||
5315 | |||
5316 | The selecting request-headers from two requests are defined to match | ||
5317 | if and only if the selecting request-headers in the first request can | ||
5318 | be transformed to the selecting request-headers in the second request | ||
5319 | |||
5320 | |||
5321 | |||
5322 | Fielding, et al. Standards Track [Page 95] | ||
5323 | |||
5324 | RFC 2616 HTTP/1.1 June 1999 | ||
5325 | |||
5326 | |||
5327 | by adding or removing linear white space (LWS) at places where this | ||
5328 | is allowed by the corresponding BNF, and/or combining multiple | ||
5329 | message-header fields with the same field name following the rules | ||
5330 | about message headers in section 4.2. | ||
5331 | |||
5332 | A Vary header field-value of "*" always fails to match and subsequent | ||
5333 | requests on that resource can only be properly interpreted by the | ||
5334 | origin server. | ||
5335 | |||
5336 | If the selecting request header fields for the cached entry do not | ||
5337 | match the selecting request header fields of the new request, then | ||
5338 | the cache MUST NOT use a cached entry to satisfy the request unless | ||
5339 | it first relays the new request to the origin server in a conditional | ||
5340 | request and the server responds with 304 (Not Modified), including an | ||
5341 | entity tag or Content-Location that indicates the entity to be used. | ||
5342 | |||
5343 | If an entity tag was assigned to a cached representation, the | ||
5344 | forwarded request SHOULD be conditional and include the entity tags | ||
5345 | in an If-None-Match header field from all its cache entries for the | ||
5346 | resource. This conveys to the server the set of entities currently | ||
5347 | held by the cache, so that if any one of these entities matches the | ||
5348 | requested entity, the server can use the ETag header field in its 304 | ||
5349 | (Not Modified) response to tell the cache which entry is appropriate. | ||
5350 | If the entity-tag of the new response matches that of an existing | ||
5351 | entry, the new response SHOULD be used to update the header fields of | ||
5352 | the existing entry, and the result MUST be returned to the client. | ||
5353 | |||
5354 | If any of the existing cache entries contains only partial content | ||
5355 | for the associated entity, its entity-tag SHOULD NOT be included in | ||
5356 | the If-None-Match header field unless the request is for a range that | ||
5357 | would be fully satisfied by that entry. | ||
5358 | |||
5359 | If a cache receives a successful response whose Content-Location | ||
5360 | field matches that of an existing cache entry for the same Request- | ||
5361 | ]URI, whose entity-tag differs from that of the existing entry, and | ||
5362 | whose Date is more recent than that of the existing entry, the | ||
5363 | existing entry SHOULD NOT be returned in response to future requests | ||
5364 | and SHOULD be deleted from the cache. | ||
5365 | |||
5366 | 13.7 Shared and Non-Shared Caches | ||
5367 | |||
5368 | For reasons of security and privacy, it is necessary to make a | ||
5369 | distinction between "shared" and "non-shared" caches. A non-shared | ||
5370 | cache is one that is accessible only to a single user. Accessibility | ||
5371 | in this case SHOULD be enforced by appropriate security mechanisms. | ||
5372 | All other caches are considered to be "shared." Other sections of | ||
5373 | |||
5374 | |||
5375 | |||
5376 | |||
5377 | |||
5378 | Fielding, et al. Standards Track [Page 96] | ||
5379 | |||
5380 | RFC 2616 HTTP/1.1 June 1999 | ||
5381 | |||
5382 | |||
5383 | this specification place certain constraints on the operation of | ||
5384 | shared caches in order to prevent loss of privacy or failure of | ||
5385 | access controls. | ||
5386 | |||
5387 | 13.8 Errors or Incomplete Response Cache Behavior | ||
5388 | |||
5389 | A cache that receives an incomplete response (for example, with fewer | ||
5390 | bytes of data than specified in a Content-Length header) MAY store | ||
5391 | the response. However, the cache MUST treat this as a partial | ||
5392 | response. Partial responses MAY be combined as described in section | ||
5393 | 13.5.4; the result might be a full response or might still be | ||
5394 | partial. A cache MUST NOT return a partial response to a client | ||
5395 | without explicitly marking it as such, using the 206 (Partial | ||
5396 | Content) status code. A cache MUST NOT return a partial response | ||
5397 | using a status code of 200 (OK). | ||
5398 | |||
5399 | If a cache receives a 5xx response while attempting to revalidate an | ||
5400 | entry, it MAY either forward this response to the requesting client, | ||
5401 | or act as if the server failed to respond. In the latter case, it MAY | ||
5402 | return a previously received response unless the cached entry | ||
5403 | includes the "must-revalidate" cache-control directive (see section | ||
5404 | 14.9). | ||
5405 | |||
5406 | 13.9 Side Effects of GET and HEAD | ||
5407 | |||
5408 | Unless the origin server explicitly prohibits the caching of their | ||
5409 | responses, the application of GET and HEAD methods to any resources | ||
5410 | SHOULD NOT have side effects that would lead to erroneous behavior if | ||
5411 | these responses are taken from a cache. They MAY still have side | ||
5412 | effects, but a cache is not required to consider such side effects in | ||
5413 | its caching decisions. Caches are always expected to observe an | ||
5414 | origin server's explicit restrictions on caching. | ||
5415 | |||
5416 | We note one exception to this rule: since some applications have | ||
5417 | traditionally used GETs and HEADs with query URLs (those containing a | ||
5418 | "?" in the rel_path part) to perform operations with significant side | ||
5419 | effects, caches MUST NOT treat responses to such URIs as fresh unless | ||
5420 | the server provides an explicit expiration time. This specifically | ||
5421 | means that responses from HTTP/1.0 servers for such URIs SHOULD NOT | ||
5422 | be taken from a cache. See section 9.1.1 for related information. | ||
5423 | |||
5424 | 13.10 Invalidation After Updates or Deletions | ||
5425 | |||
5426 | The effect of certain methods performed on a resource at the origin | ||
5427 | server might cause one or more existing cache entries to become non- | ||
5428 | transparently invalid. That is, although they might continue to be | ||
5429 | "fresh," they do not accurately reflect what the origin server would | ||
5430 | return for a new request on that resource. | ||
5431 | |||
5432 | |||
5433 | |||
5434 | Fielding, et al. Standards Track [Page 97] | ||
5435 | |||
5436 | RFC 2616 HTTP/1.1 June 1999 | ||
5437 | |||
5438 | |||
5439 | There is no way for the HTTP protocol to guarantee that all such | ||
5440 | cache entries are marked invalid. For example, the request that | ||
5441 | caused the change at the origin server might not have gone through | ||
5442 | the proxy where a cache entry is stored. However, several rules help | ||
5443 | reduce the likelihood of erroneous behavior. | ||
5444 | |||
5445 | In this section, the phrase "invalidate an entity" means that the | ||
5446 | cache will either remove all instances of that entity from its | ||
5447 | storage, or will mark these as "invalid" and in need of a mandatory | ||
5448 | revalidation before they can be returned in response to a subsequent | ||
5449 | request. | ||
5450 | |||
5451 | Some HTTP methods MUST cause a cache to invalidate an entity. This is | ||
5452 | either the entity referred to by the Request-URI, or by the Location | ||
5453 | or Content-Location headers (if present). These methods are: | ||
5454 | |||
5455 | - PUT | ||
5456 | |||
5457 | - DELETE | ||
5458 | |||
5459 | - POST | ||
5460 | |||
5461 | In order to prevent denial of service attacks, an invalidation based | ||
5462 | on the URI in a Location or Content-Location header MUST only be | ||
5463 | performed if the host part is the same as in the Request-URI. | ||
5464 | |||
5465 | A cache that passes through requests for methods it does not | ||
5466 | understand SHOULD invalidate any entities referred to by the | ||
5467 | Request-URI. | ||
5468 | |||
5469 | 13.11 Write-Through Mandatory | ||
5470 | |||
5471 | All methods that might be expected to cause modifications to the | ||
5472 | origin server's resources MUST be written through to the origin | ||
5473 | server. This currently includes all methods except for GET and HEAD. | ||
5474 | A cache MUST NOT reply to such a request from a client before having | ||
5475 | transmitted the request to the inbound server, and having received a | ||
5476 | corresponding response from the inbound server. This does not prevent | ||
5477 | a proxy cache from sending a 100 (Continue) response before the | ||
5478 | inbound server has sent its final reply. | ||
5479 | |||
5480 | The alternative (known as "write-back" or "copy-back" caching) is not | ||
5481 | allowed in HTTP/1.1, due to the difficulty of providing consistent | ||
5482 | updates and the problems arising from server, cache, or network | ||
5483 | failure prior to write-back. | ||
5484 | |||
5485 | |||
5486 | |||
5487 | |||
5488 | |||
5489 | |||
5490 | Fielding, et al. Standards Track [Page 98] | ||
5491 | |||
5492 | RFC 2616 HTTP/1.1 June 1999 | ||
5493 | |||
5494 | |||
5495 | 13.12 Cache Replacement | ||
5496 | |||
5497 | If a new cacheable (see sections 14.9.2, 13.2.5, 13.2.6 and 13.8) | ||
5498 | response is received from a resource while any existing responses for | ||
5499 | the same resource are cached, the cache SHOULD use the new response | ||
5500 | to reply to the current request. It MAY insert it into cache storage | ||
5501 | and MAY, if it meets all other requirements, use it to respond to any | ||
5502 | future requests that would previously have caused the old response to | ||
5503 | be returned. If it inserts the new response into cache storage the | ||
5504 | rules in section 13.5.3 apply. | ||
5505 | |||
5506 | Note: a new response that has an older Date header value than | ||
5507 | existing cached responses is not cacheable. | ||
5508 | |||
5509 | 13.13 History Lists | ||
5510 | |||
5511 | User agents often have history mechanisms, such as "Back" buttons and | ||
5512 | history lists, which can be used to redisplay an entity retrieved | ||
5513 | earlier in a session. | ||
5514 | |||
5515 | History mechanisms and caches are different. In particular history | ||
5516 | mechanisms SHOULD NOT try to show a semantically transparent view of | ||
5517 | the current state of a resource. Rather, a history mechanism is meant | ||
5518 | to show exactly what the user saw at the time when the resource was | ||
5519 | retrieved. | ||
5520 | |||
5521 | By default, an expiration time does not apply to history mechanisms. | ||
5522 | If the entity is still in storage, a history mechanism SHOULD display | ||
5523 | it even if the entity has expired, unless the user has specifically | ||
5524 | configured the agent to refresh expired history documents. | ||
5525 | |||
5526 | This is not to be construed to prohibit the history mechanism from | ||
5527 | telling the user that a view might be stale. | ||
5528 | |||
5529 | Note: if history list mechanisms unnecessarily prevent users from | ||
5530 | viewing stale resources, this will tend to force service authors | ||
5531 | to avoid using HTTP expiration controls and cache controls when | ||
5532 | they would otherwise like to. Service authors may consider it | ||
5533 | important that users not be presented with error messages or | ||
5534 | warning messages when they use navigation controls (such as BACK) | ||
5535 | to view previously fetched resources. Even though sometimes such | ||
5536 | resources ought not to cached, or ought to expire quickly, user | ||
5537 | interface considerations may force service authors to resort to | ||
5538 | other means of preventing caching (e.g. "once-only" URLs) in order | ||
5539 | not to suffer the effects of improperly functioning history | ||
5540 | mechanisms. | ||
5541 | |||
5542 | |||
5543 | |||
5544 | |||
5545 | |||
5546 | Fielding, et al. Standards Track [Page 99] | ||
5547 | |||
5548 | RFC 2616 HTTP/1.1 June 1999 | ||
5549 | |||
5550 | |||
5551 | 14 Header Field Definitions | ||
5552 | |||
5553 | This section defines the syntax and semantics of all standard | ||
5554 | HTTP/1.1 header fields. For entity-header fields, both sender and | ||
5555 | recipient refer to either the client or the server, depending on who | ||
5556 | sends and who receives the entity. | ||
5557 | |||
5558 | 14.1 Accept | ||
5559 | |||
5560 | The Accept request-header field can be used to specify certain media | ||
5561 | types which are acceptable for the response. Accept headers can be | ||
5562 | used to indicate that the request is specifically limited to a small | ||
5563 | set of desired types, as in the case of a request for an in-line | ||
5564 | image. | ||
5565 | |||
5566 | Accept = "Accept" ":" | ||
5567 | #( media-range [ accept-params ] ) | ||
5568 | |||
5569 | media-range = ( "*/*" | ||
5570 | | ( type "/" "*" ) | ||
5571 | | ( type "/" subtype ) | ||
5572 | ) *( ";" parameter ) | ||
5573 | accept-params = ";" "q" "=" qvalue *( accept-extension ) | ||
5574 | accept-extension = ";" token [ "=" ( token | quoted-string ) ] | ||
5575 | |||
5576 | The asterisk "*" character is used to group media types into ranges, | ||
5577 | with "*/*" indicating all media types and "type/*" indicating all | ||
5578 | subtypes of that type. The media-range MAY include media type | ||
5579 | parameters that are applicable to that range. | ||
5580 | |||
5581 | Each media-range MAY be followed by one or more accept-params, | ||
5582 | beginning with the "q" parameter for indicating a relative quality | ||
5583 | factor. The first "q" parameter (if any) separates the media-range | ||
5584 | parameter(s) from the accept-params. Quality factors allow the user | ||
5585 | or user agent to indicate the relative degree of preference for that | ||
5586 | media-range, using the qvalue scale from 0 to 1 (section 3.9). The | ||
5587 | default value is q=1. | ||
5588 | |||
5589 | Note: Use of the "q" parameter name to separate media type | ||
5590 | parameters from Accept extension parameters is due to historical | ||
5591 | practice. Although this prevents any media type parameter named | ||
5592 | "q" from being used with a media range, such an event is believed | ||
5593 | to be unlikely given the lack of any "q" parameters in the IANA | ||
5594 | media type registry and the rare usage of any media type | ||
5595 | parameters in Accept. Future media types are discouraged from | ||
5596 | registering any parameter named "q". | ||
5597 | |||
5598 | |||
5599 | |||
5600 | |||
5601 | |||
5602 | Fielding, et al. Standards Track [Page 100] | ||
5603 | |||
5604 | RFC 2616 HTTP/1.1 June 1999 | ||
5605 | |||
5606 | |||
5607 | The example | ||
5608 | |||
5609 | Accept: audio/*; q=0.2, audio/basic | ||
5610 | |||
5611 | SHOULD be interpreted as "I prefer audio/basic, but send me any audio | ||
5612 | type if it is the best available after an 80% mark-down in quality." | ||
5613 | |||
5614 | If no Accept header field is present, then it is assumed that the | ||
5615 | client accepts all media types. If an Accept header field is present, | ||
5616 | and if the server cannot send a response which is acceptable | ||
5617 | according to the combined Accept field value, then the server SHOULD | ||
5618 | send a 406 (not acceptable) response. | ||
5619 | |||
5620 | A more elaborate example is | ||
5621 | |||
5622 | Accept: text/plain; q=0.5, text/html, | ||
5623 | text/x-dvi; q=0.8, text/x-c | ||
5624 | |||
5625 | Verbally, this would be interpreted as "text/html and text/x-c are | ||
5626 | the preferred media types, but if they do not exist, then send the | ||
5627 | text/x-dvi entity, and if that does not exist, send the text/plain | ||
5628 | entity." | ||
5629 | |||
5630 | Media ranges can be overridden by more specific media ranges or | ||
5631 | specific media types. If more than one media range applies to a given | ||
5632 | type, the most specific reference has precedence. For example, | ||
5633 | |||
5634 | Accept: text/*, text/html, text/html;level=1, */* | ||
5635 | |||
5636 | have the following precedence: | ||
5637 | |||
5638 | 1) text/html;level=1 | ||
5639 | 2) text/html | ||
5640 | 3) text/* | ||
5641 | 4) */* | ||
5642 | |||
5643 | The media type quality factor associated with a given type is | ||
5644 | determined by finding the media range with the highest precedence | ||
5645 | which matches that type. For example, | ||
5646 | |||
5647 | Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, | ||
5648 | text/html;level=2;q=0.4, */*;q=0.5 | ||
5649 | |||
5650 | would cause the following values to be associated: | ||
5651 | |||
5652 | text/html;level=1 = 1 | ||
5653 | text/html = 0.7 | ||
5654 | text/plain = 0.3 | ||
5655 | |||
5656 | |||
5657 | |||
5658 | Fielding, et al. Standards Track [Page 101] | ||
5659 | |||
5660 | RFC 2616 HTTP/1.1 June 1999 | ||
5661 | |||
5662 | |||
5663 | image/jpeg = 0.5 | ||
5664 | text/html;level=2 = 0.4 | ||
5665 | text/html;level=3 = 0.7 | ||
5666 | |||
5667 | Note: A user agent might be provided with a default set of quality | ||
5668 | values for certain media ranges. However, unless the user agent is | ||
5669 | a closed system which cannot interact with other rendering agents, | ||
5670 | this default set ought to be configurable by the user. | ||
5671 | |||
5672 | 14.2 Accept-Charset | ||
5673 | |||
5674 | The Accept-Charset request-header field can be used to indicate what | ||
5675 | character sets are acceptable for the response. This field allows | ||
5676 | clients capable of understanding more comprehensive or special- | ||
5677 | purpose character sets to signal that capability to a server which is | ||
5678 | capable of representing documents in those character sets. | ||
5679 | |||
5680 | Accept-Charset = "Accept-Charset" ":" | ||
5681 | 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] ) | ||
5682 | |||
5683 | |||
5684 | Character set values are described in section 3.4. Each charset MAY | ||
5685 | be given an associated quality value which represents the user's | ||
5686 | preference for that charset. The default value is q=1. An example is | ||
5687 | |||
5688 | Accept-Charset: iso-8859-5, unicode-1-1;q=0.8 | ||
5689 | |||
5690 | The special value "*", if present in the Accept-Charset field, | ||
5691 | matches every character set (including ISO-8859-1) which is not | ||
5692 | mentioned elsewhere in the Accept-Charset field. If no "*" is present | ||
5693 | in an Accept-Charset field, then all character sets not explicitly | ||
5694 | mentioned get a quality value of 0, except for ISO-8859-1, which gets | ||
5695 | a quality value of 1 if not explicitly mentioned. | ||
5696 | |||
5697 | If no Accept-Charset header is present, the default is that any | ||
5698 | character set is acceptable. If an Accept-Charset header is present, | ||
5699 | and if the server cannot send a response which is acceptable | ||
5700 | according to the Accept-Charset header, then the server SHOULD send | ||
5701 | an error response with the 406 (not acceptable) status code, though | ||
5702 | the sending of an unacceptable response is also allowed. | ||
5703 | |||
5704 | 14.3 Accept-Encoding | ||
5705 | |||
5706 | The Accept-Encoding request-header field is similar to Accept, but | ||
5707 | restricts the content-codings (section 3.5) that are acceptable in | ||
5708 | the response. | ||
5709 | |||
5710 | Accept-Encoding = "Accept-Encoding" ":" | ||
5711 | |||
5712 | |||
5713 | |||
5714 | Fielding, et al. Standards Track [Page 102] | ||
5715 | |||
5716 | RFC 2616 HTTP/1.1 June 1999 | ||
5717 | |||
5718 | |||
5719 | 1#( codings [ ";" "q" "=" qvalue ] ) | ||
5720 | codings = ( content-coding | "*" ) | ||
5721 | |||
5722 | Examples of its use are: | ||
5723 | |||
5724 | Accept-Encoding: compress, gzip | ||
5725 | Accept-Encoding: | ||
5726 | Accept-Encoding: * | ||
5727 | Accept-Encoding: compress;q=0.5, gzip;q=1.0 | ||
5728 | Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0 | ||
5729 | |||
5730 | A server tests whether a content-coding is acceptable, according to | ||
5731 | an Accept-Encoding field, using these rules: | ||
5732 | |||
5733 | 1. If the content-coding is one of the content-codings listed in | ||
5734 | the Accept-Encoding field, then it is acceptable, unless it is | ||
5735 | accompanied by a qvalue of 0. (As defined in section 3.9, a | ||
5736 | qvalue of 0 means "not acceptable.") | ||
5737 | |||
5738 | 2. The special "*" symbol in an Accept-Encoding field matches any | ||
5739 | available content-coding not explicitly listed in the header | ||
5740 | field. | ||
5741 | |||
5742 | 3. If multiple content-codings are acceptable, then the acceptable | ||
5743 | content-coding with the highest non-zero qvalue is preferred. | ||
5744 | |||
5745 | 4. The "identity" content-coding is always acceptable, unless | ||
5746 | specifically refused because the Accept-Encoding field includes | ||
5747 | "identity;q=0", or because the field includes "*;q=0" and does | ||
5748 | not explicitly include the "identity" content-coding. If the | ||
5749 | Accept-Encoding field-value is empty, then only the "identity" | ||
5750 | encoding is acceptable. | ||
5751 | |||
5752 | If an Accept-Encoding field is present in a request, and if the | ||
5753 | server cannot send a response which is acceptable according to the | ||
5754 | Accept-Encoding header, then the server SHOULD send an error response | ||
5755 | with the 406 (Not Acceptable) status code. | ||
5756 | |||
5757 | If no Accept-Encoding field is present in a request, the server MAY | ||
5758 | assume that the client will accept any content coding. In this case, | ||
5759 | if "identity" is one of the available content-codings, then the | ||
5760 | server SHOULD use the "identity" content-coding, unless it has | ||
5761 | additional information that a different content-coding is meaningful | ||
5762 | to the client. | ||
5763 | |||
5764 | Note: If the request does not include an Accept-Encoding field, | ||
5765 | and if the "identity" content-coding is unavailable, then | ||
5766 | content-codings commonly understood by HTTP/1.0 clients (i.e., | ||
5767 | |||
5768 | |||
5769 | |||
5770 | Fielding, et al. Standards Track [Page 103] | ||
5771 | |||
5772 | RFC 2616 HTTP/1.1 June 1999 | ||
5773 | |||
5774 | |||
5775 | "gzip" and "compress") are preferred; some older clients | ||
5776 | improperly display messages sent with other content-codings. The | ||
5777 | server might also make this decision based on information about | ||
5778 | the particular user-agent or client. | ||
5779 | |||
5780 | Note: Most HTTP/1.0 applications do not recognize or obey qvalues | ||
5781 | associated with content-codings. This means that qvalues will not | ||
5782 | work and are not permitted with x-gzip or x-compress. | ||
5783 | |||
5784 | 14.4 Accept-Language | ||
5785 | |||
5786 | The Accept-Language request-header field is similar to Accept, but | ||
5787 | restricts the set of natural languages that are preferred as a | ||
5788 | response to the request. Language tags are defined in section 3.10. | ||
5789 | |||
5790 | Accept-Language = "Accept-Language" ":" | ||
5791 | 1#( language-range [ ";" "q" "=" qvalue ] ) | ||
5792 | language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) | ||
5793 | |||
5794 | Each language-range MAY be given an associated quality value which | ||
5795 | represents an estimate of the user's preference for the languages | ||
5796 | specified by that range. The quality value defaults to "q=1". For | ||
5797 | example, | ||
5798 | |||
5799 | Accept-Language: da, en-gb;q=0.8, en;q=0.7 | ||
5800 | |||
5801 | would mean: "I prefer Danish, but will accept British English and | ||
5802 | other types of English." A language-range matches a language-tag if | ||
5803 | it exactly equals the tag, or if it exactly equals a prefix of the | ||
5804 | tag such that the first tag character following the prefix is "-". | ||
5805 | The special range "*", if present in the Accept-Language field, | ||
5806 | matches every tag not matched by any other range present in the | ||
5807 | Accept-Language field. | ||
5808 | |||
5809 | Note: This use of a prefix matching rule does not imply that | ||
5810 | language tags are assigned to languages in such a way that it is | ||
5811 | always true that if a user understands a language with a certain | ||
5812 | tag, then this user will also understand all languages with tags | ||
5813 | for which this tag is a prefix. The prefix rule simply allows the | ||
5814 | use of prefix tags if this is the case. | ||
5815 | |||
5816 | The language quality factor assigned to a language-tag by the | ||
5817 | Accept-Language field is the quality value of the longest language- | ||
5818 | range in the field that matches the language-tag. If no language- | ||
5819 | range in the field matches the tag, the language quality factor | ||
5820 | assigned is 0. If no Accept-Language header is present in the | ||
5821 | request, the server | ||
5822 | |||
5823 | |||
5824 | |||
5825 | |||
5826 | Fielding, et al. Standards Track [Page 104] | ||
5827 | |||
5828 | RFC 2616 HTTP/1.1 June 1999 | ||
5829 | |||
5830 | |||
5831 | SHOULD assume that all languages are equally acceptable. If an | ||
5832 | Accept-Language header is present, then all languages which are | ||
5833 | assigned a quality factor greater than 0 are acceptable. | ||
5834 | |||
5835 | It might be contrary to the privacy expectations of the user to send | ||
5836 | an Accept-Language header with the complete linguistic preferences of | ||
5837 | the user in every request. For a discussion of this issue, see | ||
5838 | section 15.1.4. | ||
5839 | |||
5840 | As intelligibility is highly dependent on the individual user, it is | ||
5841 | recommended that client applications make the choice of linguistic | ||
5842 | preference available to the user. If the choice is not made | ||
5843 | available, then the Accept-Language header field MUST NOT be given in | ||
5844 | the request. | ||
5845 | |||
5846 | Note: When making the choice of linguistic preference available to | ||
5847 | the user, we remind implementors of the fact that users are not | ||
5848 | familiar with the details of language matching as described above, | ||
5849 | and should provide appropriate guidance. As an example, users | ||
5850 | might assume that on selecting "en-gb", they will be served any | ||
5851 | kind of English document if British English is not available. A | ||
5852 | user agent might suggest in such a case to add "en" to get the | ||
5853 | best matching behavior. | ||
5854 | |||
5855 | 14.5 Accept-Ranges | ||
5856 | |||
5857 | The Accept-Ranges response-header field allows the server to | ||
5858 | indicate its acceptance of range requests for a resource: | ||
5859 | |||
5860 | Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges | ||
5861 | acceptable-ranges = 1#range-unit | "none" | ||
5862 | |||
5863 | Origin servers that accept byte-range requests MAY send | ||
5864 | |||
5865 | Accept-Ranges: bytes | ||
5866 | |||
5867 | but are not required to do so. Clients MAY generate byte-range | ||
5868 | requests without having received this header for the resource | ||
5869 | involved. Range units are defined in section 3.12. | ||
5870 | |||
5871 | Servers that do not accept any kind of range request for a | ||
5872 | resource MAY send | ||
5873 | |||
5874 | Accept-Ranges: none | ||
5875 | |||
5876 | to advise the client not to attempt a range request. | ||
5877 | |||
5878 | |||
5879 | |||
5880 | |||
5881 | |||
5882 | Fielding, et al. Standards Track [Page 105] | ||
5883 | |||
5884 | RFC 2616 HTTP/1.1 June 1999 | ||
5885 | |||
5886 | |||
5887 | 14.6 Age | ||
5888 | |||
5889 | The Age response-header field conveys the sender's estimate of the | ||
5890 | amount of time since the response (or its revalidation) was | ||
5891 | generated at the origin server. A cached response is "fresh" if | ||
5892 | its age does not exceed its freshness lifetime. Age values are | ||
5893 | calculated as specified in section 13.2.3. | ||
5894 | |||
5895 | Age = "Age" ":" age-value | ||
5896 | age-value = delta-seconds | ||
5897 | |||
5898 | Age values are non-negative decimal integers, representing time in | ||
5899 | seconds. | ||
5900 | |||
5901 | If a cache receives a value larger than the largest positive | ||
5902 | integer it can represent, or if any of its age calculations | ||
5903 | overflows, it MUST transmit an Age header with a value of | ||
5904 | 2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST | ||
5905 | include an Age header field in every response generated from its | ||
5906 | own cache. Caches SHOULD use an arithmetic type of at least 31 | ||
5907 | bits of range. | ||
5908 | |||
5909 | 14.7 Allow | ||
5910 | |||
5911 | The Allow entity-header field lists the set of methods supported | ||
5912 | by the resource identified by the Request-URI. The purpose of this | ||
5913 | field is strictly to inform the recipient of valid methods | ||
5914 | associated with the resource. An Allow header field MUST be | ||
5915 | present in a 405 (Method Not Allowed) response. | ||
5916 | |||
5917 | Allow = "Allow" ":" #Method | ||
5918 | |||
5919 | Example of use: | ||
5920 | |||
5921 | Allow: GET, HEAD, PUT | ||
5922 | |||
5923 | This field cannot prevent a client from trying other methods. | ||
5924 | However, the indications given by the Allow header field value | ||
5925 | SHOULD be followed. The actual set of allowed methods is defined | ||
5926 | by the origin server at the time of each request. | ||
5927 | |||
5928 | The Allow header field MAY be provided with a PUT request to | ||
5929 | recommend the methods to be supported by the new or modified | ||
5930 | resource. The server is not required to support these methods and | ||
5931 | SHOULD include an Allow header in the response giving the actual | ||
5932 | supported methods. | ||
5933 | |||
5934 | |||
5935 | |||
5936 | |||
5937 | |||
5938 | Fielding, et al. Standards Track [Page 106] | ||
5939 | |||
5940 | RFC 2616 HTTP/1.1 June 1999 | ||
5941 | |||
5942 | |||
5943 | A proxy MUST NOT modify the Allow header field even if it does not | ||
5944 | understand all the methods specified, since the user agent might | ||
5945 | have other means of communicating with the origin server. | ||
5946 | |||
5947 | 14.8 Authorization | ||
5948 | |||
5949 | A user agent that wishes to authenticate itself with a server-- | ||
5950 | usually, but not necessarily, after receiving a 401 response--does | ||
5951 | so by including an Authorization request-header field with the | ||
5952 | request. The Authorization field value consists of credentials | ||
5953 | containing the authentication information of the user agent for | ||
5954 | the realm of the resource being requested. | ||
5955 | |||
5956 | Authorization = "Authorization" ":" credentials | ||
5957 | |||
5958 | HTTP access authentication is described in "HTTP Authentication: | ||
5959 | Basic and Digest Access Authentication" [43]. If a request is | ||
5960 | authenticated and a realm specified, the same credentials SHOULD | ||
5961 | be valid for all other requests within this realm (assuming that | ||
5962 | the authentication scheme itself does not require otherwise, such | ||
5963 | as credentials that vary according to a challenge value or using | ||
5964 | synchronized clocks). | ||
5965 | |||
5966 | When a shared cache (see section 13.7) receives a request | ||
5967 | containing an Authorization field, it MUST NOT return the | ||
5968 | corresponding response as a reply to any other request, unless one | ||
5969 | of the following specific exceptions holds: | ||
5970 | |||
5971 | 1. If the response includes the "s-maxage" cache-control | ||
5972 | directive, the cache MAY use that response in replying to a | ||
5973 | subsequent request. But (if the specified maximum age has | ||
5974 | passed) a proxy cache MUST first revalidate it with the origin | ||
5975 | server, using the request-headers from the new request to allow | ||
5976 | the origin server to authenticate the new request. (This is the | ||
5977 | defined behavior for s-maxage.) If the response includes "s- | ||
5978 | maxage=0", the proxy MUST always revalidate it before re-using | ||
5979 | it. | ||
5980 | |||
5981 | 2. If the response includes the "must-revalidate" cache-control | ||
5982 | directive, the cache MAY use that response in replying to a | ||
5983 | subsequent request. But if the response is stale, all caches | ||
5984 | MUST first revalidate it with the origin server, using the | ||
5985 | request-headers from the new request to allow the origin server | ||
5986 | to authenticate the new request. | ||
5987 | |||
5988 | 3. If the response includes the "public" cache-control directive, | ||
5989 | it MAY be returned in reply to any subsequent request. | ||
5990 | |||
5991 | |||
5992 | |||
5993 | |||
5994 | Fielding, et al. Standards Track [Page 107] | ||
5995 | |||
5996 | RFC 2616 HTTP/1.1 June 1999 | ||
5997 | |||
5998 | |||
5999 | 14.9 Cache-Control | ||
6000 | |||
6001 | The Cache-Control general-header field is used to specify directives | ||
6002 | that MUST be obeyed by all caching mechanisms along the | ||
6003 | request/response chain. The directives specify behavior intended to | ||
6004 | prevent caches from adversely interfering with the request or | ||
6005 | response. These directives typically override the default caching | ||
6006 | algorithms. Cache directives are unidirectional in that the presence | ||
6007 | of a directive in a request does not imply that the same directive is | ||
6008 | to be given in the response. | ||
6009 | |||
6010 | Note that HTTP/1.0 caches might not implement Cache-Control and | ||
6011 | might only implement Pragma: no-cache (see section 14.32). | ||
6012 | |||
6013 | Cache directives MUST be passed through by a proxy or gateway | ||
6014 | application, regardless of their significance to that application, | ||
6015 | since the directives might be applicable to all recipients along the | ||
6016 | request/response chain. It is not possible to specify a cache- | ||
6017 | directive for a specific cache. | ||
6018 | |||
6019 | Cache-Control = "Cache-Control" ":" 1#cache-directive | ||
6020 | |||
6021 | cache-directive = cache-request-directive | ||
6022 | | cache-response-directive | ||
6023 | |||
6024 | cache-request-directive = | ||
6025 | "no-cache" ; Section 14.9.1 | ||
6026 | | "no-store" ; Section 14.9.2 | ||
6027 | | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4 | ||
6028 | | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3 | ||
6029 | | "min-fresh" "=" delta-seconds ; Section 14.9.3 | ||
6030 | | "no-transform" ; Section 14.9.5 | ||
6031 | | "only-if-cached" ; Section 14.9.4 | ||
6032 | | cache-extension ; Section 14.9.6 | ||
6033 | |||
6034 | cache-response-directive = | ||
6035 | "public" ; Section 14.9.1 | ||
6036 | | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1 | ||
6037 | | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1 | ||
6038 | | "no-store" ; Section 14.9.2 | ||
6039 | | "no-transform" ; Section 14.9.5 | ||
6040 | | "must-revalidate" ; Section 14.9.4 | ||
6041 | | "proxy-revalidate" ; Section 14.9.4 | ||
6042 | | "max-age" "=" delta-seconds ; Section 14.9.3 | ||
6043 | | "s-maxage" "=" delta-seconds ; Section 14.9.3 | ||
6044 | | cache-extension ; Section 14.9.6 | ||
6045 | |||
6046 | cache-extension = token [ "=" ( token | quoted-string ) ] | ||
6047 | |||
6048 | |||
6049 | |||
6050 | Fielding, et al. Standards Track [Page 108] | ||
6051 | |||
6052 | RFC 2616 HTTP/1.1 June 1999 | ||
6053 | |||
6054 | |||
6055 | When a directive appears without any 1#field-name parameter, the | ||
6056 | directive applies to the entire request or response. When such a | ||
6057 | directive appears with a 1#field-name parameter, it applies only to | ||
6058 | the named field or fields, and not to the rest of the request or | ||
6059 | response. This mechanism supports extensibility; implementations of | ||
6060 | future versions of the HTTP protocol might apply these directives to | ||
6061 | header fields not defined in HTTP/1.1. | ||
6062 | |||
6063 | The cache-control directives can be broken down into these general | ||
6064 | categories: | ||
6065 | |||
6066 | - Restrictions on what are cacheable; these may only be imposed by | ||
6067 | the origin server. | ||
6068 | |||
6069 | - Restrictions on what may be stored by a cache; these may be | ||
6070 | imposed by either the origin server or the user agent. | ||
6071 | |||
6072 | - Modifications of the basic expiration mechanism; these may be | ||
6073 | imposed by either the origin server or the user agent. | ||
6074 | |||
6075 | - Controls over cache revalidation and reload; these may only be | ||
6076 | imposed by a user agent. | ||
6077 | |||
6078 | - Control over transformation of entities. | ||
6079 | |||
6080 | - Extensions to the caching system. | ||
6081 | |||
6082 | 14.9.1 What is Cacheable | ||
6083 | |||
6084 | By default, a response is cacheable if the requirements of the | ||
6085 | request method, request header fields, and the response status | ||
6086 | indicate that it is cacheable. Section 13.4 summarizes these defaults | ||
6087 | for cacheability. The following Cache-Control response directives | ||
6088 | allow an origin server to override the default cacheability of a | ||
6089 | response: | ||
6090 | |||
6091 | public | ||
6092 | Indicates that the response MAY be cached by any cache, even if it | ||
6093 | would normally be non-cacheable or cacheable only within a non- | ||
6094 | shared cache. (See also Authorization, section 14.8, for | ||
6095 | additional details.) | ||
6096 | |||
6097 | private | ||
6098 | Indicates that all or part of the response message is intended for | ||
6099 | a single user and MUST NOT be cached by a shared cache. This | ||
6100 | allows an origin server to state that the specified parts of the | ||
6101 | |||
6102 | |||
6103 | |||
6104 | |||
6105 | |||
6106 | Fielding, et al. Standards Track [Page 109] | ||
6107 | |||
6108 | RFC 2616 HTTP/1.1 June 1999 | ||
6109 | |||
6110 | |||
6111 | response are intended for only one user and are not a valid | ||
6112 | response for requests by other users. A private (non-shared) cache | ||
6113 | MAY cache the response. | ||
6114 | |||
6115 | Note: This usage of the word private only controls where the | ||
6116 | response may be cached, and cannot ensure the privacy of the | ||
6117 | message content. | ||
6118 | |||
6119 | no-cache | ||
6120 | If the no-cache directive does not specify a field-name, then a | ||
6121 | cache MUST NOT use the response to satisfy a subsequent request | ||
6122 | without successful revalidation with the origin server. This | ||
6123 | allows an origin server to prevent caching even by caches that | ||
6124 | have been configured to return stale responses to client requests. | ||
6125 | |||
6126 | If the no-cache directive does specify one or more field-names, | ||
6127 | then a cache MAY use the response to satisfy a subsequent request, | ||
6128 | subject to any other restrictions on caching. However, the | ||
6129 | specified field-name(s) MUST NOT be sent in the response to a | ||
6130 | subsequent request without successful revalidation with the origin | ||
6131 | server. This allows an origin server to prevent the re-use of | ||
6132 | certain header fields in a response, while still allowing caching | ||
6133 | of the rest of the response. | ||
6134 | |||
6135 | Note: Most HTTP/1.0 caches will not recognize or obey this | ||
6136 | directive. | ||
6137 | |||
6138 | 14.9.2 What May be Stored by Caches | ||
6139 | |||
6140 | no-store | ||
6141 | The purpose of the no-store directive is to prevent the | ||
6142 | inadvertent release or retention of sensitive information (for | ||
6143 | example, on backup tapes). The no-store directive applies to the | ||
6144 | entire message, and MAY be sent either in a response or in a | ||
6145 | request. If sent in a request, a cache MUST NOT store any part of | ||
6146 | either this request or any response to it. If sent in a response, | ||
6147 | a cache MUST NOT store any part of either this response or the | ||
6148 | request that elicited it. This directive applies to both non- | ||
6149 | shared and shared caches. "MUST NOT store" in this context means | ||
6150 | that the cache MUST NOT intentionally store the information in | ||
6151 | non-volatile storage, and MUST make a best-effort attempt to | ||
6152 | remove the information from volatile storage as promptly as | ||
6153 | possible after forwarding it. | ||
6154 | |||
6155 | Even when this directive is associated with a response, users | ||
6156 | might explicitly store such a response outside of the caching | ||
6157 | system (e.g., with a "Save As" dialog). History buffers MAY store | ||
6158 | such responses as part of their normal operation. | ||
6159 | |||
6160 | |||
6161 | |||
6162 | Fielding, et al. Standards Track [Page 110] | ||
6163 | |||
6164 | RFC 2616 HTTP/1.1 June 1999 | ||
6165 | |||
6166 | |||
6167 | The purpose of this directive is to meet the stated requirements | ||
6168 | of certain users and service authors who are concerned about | ||
6169 | accidental releases of information via unanticipated accesses to | ||
6170 | cache data structures. While the use of this directive might | ||
6171 | improve privacy in some cases, we caution that it is NOT in any | ||
6172 | way a reliable or sufficient mechanism for ensuring privacy. In | ||
6173 | particular, malicious or compromised caches might not recognize or | ||
6174 | obey this directive, and communications networks might be | ||
6175 | vulnerable to eavesdropping. | ||
6176 | |||
6177 | 14.9.3 Modifications of the Basic Expiration Mechanism | ||
6178 | |||
6179 | The expiration time of an entity MAY be specified by the origin | ||
6180 | server using the Expires header (see section 14.21). Alternatively, | ||
6181 | it MAY be specified using the max-age directive in a response. When | ||
6182 | the max-age cache-control directive is present in a cached response, | ||
6183 | the response is stale if its current age is greater than the age | ||
6184 | value given (in seconds) at the time of a new request for that | ||
6185 | resource. The max-age directive on a response implies that the | ||
6186 | response is cacheable (i.e., "public") unless some other, more | ||
6187 | restrictive cache directive is also present. | ||
6188 | |||
6189 | If a response includes both an Expires header and a max-age | ||
6190 | directive, the max-age directive overrides the Expires header, even | ||
6191 | if the Expires header is more restrictive. This rule allows an origin | ||
6192 | server to provide, for a given response, a longer expiration time to | ||
6193 | an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be | ||
6194 | useful if certain HTTP/1.0 caches improperly calculate ages or | ||
6195 | expiration times, perhaps due to desynchronized clocks. | ||
6196 | |||
6197 | Many HTTP/1.0 cache implementations will treat an Expires value that | ||
6198 | is less than or equal to the response Date value as being equivalent | ||
6199 | to the Cache-Control response directive "no-cache". If an HTTP/1.1 | ||
6200 | cache receives such a response, and the response does not include a | ||
6201 | Cache-Control header field, it SHOULD consider the response to be | ||
6202 | non-cacheable in order to retain compatibility with HTTP/1.0 servers. | ||
6203 | |||
6204 | Note: An origin server might wish to use a relatively new HTTP | ||
6205 | cache control feature, such as the "private" directive, on a | ||
6206 | network including older caches that do not understand that | ||
6207 | feature. The origin server will need to combine the new feature | ||
6208 | with an Expires field whose value is less than or equal to the | ||
6209 | Date value. This will prevent older caches from improperly | ||
6210 | caching the response. | ||
6211 | |||
6212 | |||
6213 | |||
6214 | |||
6215 | |||
6216 | |||
6217 | |||
6218 | Fielding, et al. Standards Track [Page 111] | ||
6219 | |||
6220 | RFC 2616 HTTP/1.1 June 1999 | ||
6221 | |||
6222 | |||
6223 | s-maxage | ||
6224 | If a response includes an s-maxage directive, then for a shared | ||
6225 | cache (but not for a private cache), the maximum age specified by | ||
6226 | this directive overrides the maximum age specified by either the | ||
6227 | max-age directive or the Expires header. The s-maxage directive | ||
6228 | also implies the semantics of the proxy-revalidate directive (see | ||
6229 | section 14.9.4), i.e., that the shared cache must not use the | ||
6230 | entry after it becomes stale to respond to a subsequent request | ||
6231 | without first revalidating it with the origin server. The s- | ||
6232 | maxage directive is always ignored by a private cache. | ||
6233 | |||
6234 | Note that most older caches, not compliant with this specification, | ||
6235 | do not implement any cache-control directives. An origin server | ||
6236 | wishing to use a cache-control directive that restricts, but does not | ||
6237 | prevent, caching by an HTTP/1.1-compliant cache MAY exploit the | ||
6238 | requirement that the max-age directive overrides the Expires header, | ||
6239 | and the fact that pre-HTTP/1.1-compliant caches do not observe the | ||
6240 | max-age directive. | ||
6241 | |||
6242 | Other directives allow a user agent to modify the basic expiration | ||
6243 | mechanism. These directives MAY be specified on a request: | ||
6244 | |||
6245 | max-age | ||
6246 | Indicates that the client is willing to accept a response whose | ||
6247 | age is no greater than the specified time in seconds. Unless max- | ||
6248 | stale directive is also included, the client is not willing to | ||
6249 | accept a stale response. | ||
6250 | |||
6251 | min-fresh | ||
6252 | Indicates that the client is willing to accept a response whose | ||
6253 | freshness lifetime is no less than its current age plus the | ||
6254 | specified time in seconds. That is, the client wants a response | ||
6255 | that will still be fresh for at least the specified number of | ||
6256 | seconds. | ||
6257 | |||
6258 | max-stale | ||
6259 | Indicates that the client is willing to accept a response that has | ||
6260 | exceeded its expiration time. If max-stale is assigned a value, | ||
6261 | then the client is willing to accept a response that has exceeded | ||
6262 | its expiration time by no more than the specified number of | ||
6263 | seconds. If no value is assigned to max-stale, then the client is | ||
6264 | willing to accept a stale response of any age. | ||
6265 | |||
6266 | If a cache returns a stale response, either because of a max-stale | ||
6267 | directive on a request, or because the cache is configured to | ||
6268 | override the expiration time of a response, the cache MUST attach a | ||
6269 | Warning header to the stale response, using Warning 110 (Response is | ||
6270 | stale). | ||
6271 | |||
6272 | |||
6273 | |||
6274 | Fielding, et al. Standards Track [Page 112] | ||
6275 | |||
6276 | RFC 2616 HTTP/1.1 June 1999 | ||
6277 | |||
6278 | |||
6279 | A cache MAY be configured to return stale responses without | ||
6280 | validation, but only if this does not conflict with any "MUST"-level | ||
6281 | requirements concerning cache validation (e.g., a "must-revalidate" | ||
6282 | cache-control directive). | ||
6283 | |||
6284 | If both the new request and the cached entry include "max-age" | ||
6285 | directives, then the lesser of the two values is used for determining | ||
6286 | the freshness of the cached entry for that request. | ||
6287 | |||
6288 | 14.9.4 Cache Revalidation and Reload Controls | ||
6289 | |||
6290 | Sometimes a user agent might want or need to insist that a cache | ||
6291 | revalidate its cache entry with the origin server (and not just with | ||
6292 | the next cache along the path to the origin server), or to reload its | ||
6293 | cache entry from the origin server. End-to-end revalidation might be | ||
6294 | necessary if either the cache or the origin server has overestimated | ||
6295 | the expiration time of the cached response. End-to-end reload may be | ||
6296 | necessary if the cache entry has become corrupted for some reason. | ||
6297 | |||
6298 | End-to-end revalidation may be requested either when the client does | ||
6299 | not have its own local cached copy, in which case we call it | ||
6300 | "unspecified end-to-end revalidation", or when the client does have a | ||
6301 | local cached copy, in which case we call it "specific end-to-end | ||
6302 | revalidation." | ||
6303 | |||
6304 | The client can specify these three kinds of action using Cache- | ||
6305 | Control request directives: | ||
6306 | |||
6307 | End-to-end reload | ||
6308 | The request includes a "no-cache" cache-control directive or, for | ||
6309 | compatibility with HTTP/1.0 clients, "Pragma: no-cache". Field | ||
6310 | names MUST NOT be included with the no-cache directive in a | ||
6311 | request. The server MUST NOT use a cached copy when responding to | ||
6312 | such a request. | ||
6313 | |||
6314 | Specific end-to-end revalidation | ||
6315 | The request includes a "max-age=0" cache-control directive, which | ||
6316 | forces each cache along the path to the origin server to | ||
6317 | revalidate its own entry, if any, with the next cache or server. | ||
6318 | The initial request includes a cache-validating conditional with | ||
6319 | the client's current validator. | ||
6320 | |||
6321 | Unspecified end-to-end revalidation | ||
6322 | The request includes "max-age=0" cache-control directive, which | ||
6323 | forces each cache along the path to the origin server to | ||
6324 | revalidate its own entry, if any, with the next cache or server. | ||
6325 | The initial request does not include a cache-validating | ||
6326 | |||
6327 | |||
6328 | |||
6329 | |||
6330 | Fielding, et al. Standards Track [Page 113] | ||
6331 | |||
6332 | RFC 2616 HTTP/1.1 June 1999 | ||
6333 | |||
6334 | |||
6335 | conditional; the first cache along the path (if any) that holds a | ||
6336 | cache entry for this resource includes a cache-validating | ||
6337 | conditional with its current validator. | ||
6338 | |||
6339 | max-age | ||
6340 | When an intermediate cache is forced, by means of a max-age=0 | ||
6341 | directive, to revalidate its own cache entry, and the client has | ||
6342 | supplied its own validator in the request, the supplied validator | ||
6343 | might differ from the validator currently stored with the cache | ||
6344 | entry. In this case, the cache MAY use either validator in making | ||
6345 | its own request without affecting semantic transparency. | ||
6346 | |||
6347 | However, the choice of validator might affect performance. The | ||
6348 | best approach is for the intermediate cache to use its own | ||
6349 | validator when making its request. If the server replies with 304 | ||
6350 | (Not Modified), then the cache can return its now validated copy | ||
6351 | to the client with a 200 (OK) response. If the server replies with | ||
6352 | a new entity and cache validator, however, the intermediate cache | ||
6353 | can compare the returned validator with the one provided in the | ||
6354 | client's request, using the strong comparison function. If the | ||
6355 | client's validator is equal to the origin server's, then the | ||
6356 | intermediate cache simply returns 304 (Not Modified). Otherwise, | ||
6357 | it returns the new entity with a 200 (OK) response. | ||
6358 | |||
6359 | If a request includes the no-cache directive, it SHOULD NOT | ||
6360 | include min-fresh, max-stale, or max-age. | ||
6361 | |||
6362 | only-if-cached | ||
6363 | In some cases, such as times of extremely poor network | ||
6364 | connectivity, a client may want a cache to return only those | ||
6365 | responses that it currently has stored, and not to reload or | ||
6366 | revalidate with the origin server. To do this, the client may | ||
6367 | include the only-if-cached directive in a request. If it receives | ||
6368 | this directive, a cache SHOULD either respond using a cached entry | ||
6369 | that is consistent with the other constraints of the request, or | ||
6370 | respond with a 504 (Gateway Timeout) status. However, if a group | ||
6371 | of caches is being operated as a unified system with good internal | ||
6372 | connectivity, such a request MAY be forwarded within that group of | ||
6373 | caches. | ||
6374 | |||
6375 | must-revalidate | ||
6376 | Because a cache MAY be configured to ignore a server's specified | ||
6377 | expiration time, and because a client request MAY include a max- | ||
6378 | stale directive (which has a similar effect), the protocol also | ||
6379 | includes a mechanism for the origin server to require revalidation | ||
6380 | of a cache entry on any subsequent use. When the must-revalidate | ||
6381 | directive is present in a response received by a cache, that cache | ||
6382 | MUST NOT use the entry after it becomes stale to respond to a | ||
6383 | |||
6384 | |||
6385 | |||
6386 | Fielding, et al. Standards Track [Page 114] | ||
6387 | |||
6388 | RFC 2616 HTTP/1.1 June 1999 | ||
6389 | |||
6390 | |||
6391 | subsequent request without first revalidating it with the origin | ||
6392 | server. (I.e., the cache MUST do an end-to-end revalidation every | ||
6393 | time, if, based solely on the origin server's Expires or max-age | ||
6394 | value, the cached response is stale.) | ||
6395 | |||
6396 | The must-revalidate directive is necessary to support reliable | ||
6397 | operation for certain protocol features. In all circumstances an | ||
6398 | HTTP/1.1 cache MUST obey the must-revalidate directive; in | ||
6399 | particular, if the cache cannot reach the origin server for any | ||
6400 | reason, it MUST generate a 504 (Gateway Timeout) response. | ||
6401 | |||
6402 | Servers SHOULD send the must-revalidate directive if and only if | ||
6403 | failure to revalidate a request on the entity could result in | ||
6404 | incorrect operation, such as a silently unexecuted financial | ||
6405 | transaction. Recipients MUST NOT take any automated action that | ||
6406 | violates this directive, and MUST NOT automatically provide an | ||
6407 | unvalidated copy of the entity if revalidation fails. | ||
6408 | |||
6409 | Although this is not recommended, user agents operating under | ||
6410 | severe connectivity constraints MAY violate this directive but, if | ||
6411 | so, MUST explicitly warn the user that an unvalidated response has | ||
6412 | been provided. The warning MUST be provided on each unvalidated | ||
6413 | access, and SHOULD require explicit user confirmation. | ||
6414 | |||
6415 | proxy-revalidate | ||
6416 | The proxy-revalidate directive has the same meaning as the must- | ||
6417 | revalidate directive, except that it does not apply to non-shared | ||
6418 | user agent caches. It can be used on a response to an | ||
6419 | authenticated request to permit the user's cache to store and | ||
6420 | later return the response without needing to revalidate it (since | ||
6421 | it has already been authenticated once by that user), while still | ||
6422 | requiring proxies that service many users to revalidate each time | ||
6423 | (in order to make sure that each user has been authenticated). | ||
6424 | Note that such authenticated responses also need the public cache | ||
6425 | control directive in order to allow them to be cached at all. | ||
6426 | |||
6427 | 14.9.5 No-Transform Directive | ||
6428 | |||
6429 | no-transform | ||
6430 | Implementors of intermediate caches (proxies) have found it useful | ||
6431 | to convert the media type of certain entity bodies. A non- | ||
6432 | transparent proxy might, for example, convert between image | ||
6433 | formats in order to save cache space or to reduce the amount of | ||
6434 | traffic on a slow link. | ||
6435 | |||
6436 | Serious operational problems occur, however, when these | ||
6437 | transformations are applied to entity bodies intended for certain | ||
6438 | kinds of applications. For example, applications for medical | ||
6439 | |||
6440 | |||
6441 | |||
6442 | Fielding, et al. Standards Track [Page 115] | ||
6443 | |||
6444 | RFC 2616 HTTP/1.1 June 1999 | ||
6445 | |||
6446 | |||
6447 | imaging, scientific data analysis and those using end-to-end | ||
6448 | authentication, all depend on receiving an entity body that is bit | ||
6449 | for bit identical to the original entity-body. | ||
6450 | |||
6451 | Therefore, if a message includes the no-transform directive, an | ||
6452 | intermediate cache or proxy MUST NOT change those headers that are | ||
6453 | listed in section 13.5.2 as being subject to the no-transform | ||
6454 | directive. This implies that the cache or proxy MUST NOT change | ||
6455 | any aspect of the entity-body that is specified by these headers, | ||
6456 | including the value of the entity-body itself. | ||
6457 | |||
6458 | 14.9.6 Cache Control Extensions | ||
6459 | |||
6460 | The Cache-Control header field can be extended through the use of one | ||
6461 | or more cache-extension tokens, each with an optional assigned value. | ||
6462 | Informational extensions (those which do not require a change in | ||
6463 | cache behavior) MAY be added without changing the semantics of other | ||
6464 | directives. Behavioral extensions are designed to work by acting as | ||
6465 | modifiers to the existing base of cache directives. Both the new | ||
6466 | directive and the standard directive are supplied, such that | ||
6467 | applications which do not understand the new directive will default | ||
6468 | to the behavior specified by the standard directive, and those that | ||
6469 | understand the new directive will recognize it as modifying the | ||
6470 | requirements associated with the standard directive. In this way, | ||
6471 | extensions to the cache-control directives can be made without | ||
6472 | requiring changes to the base protocol. | ||
6473 | |||
6474 | This extension mechanism depends on an HTTP cache obeying all of the | ||
6475 | cache-control directives defined for its native HTTP-version, obeying | ||
6476 | certain extensions, and ignoring all directives that it does not | ||
6477 | understand. | ||
6478 | |||
6479 | For example, consider a hypothetical new response directive called | ||
6480 | community which acts as a modifier to the private directive. We | ||
6481 | define this new directive to mean that, in addition to any non-shared | ||
6482 | cache, any cache which is shared only by members of the community | ||
6483 | named within its value may cache the response. An origin server | ||
6484 | wishing to allow the UCI community to use an otherwise private | ||
6485 | response in their shared cache(s) could do so by including | ||
6486 | |||
6487 | Cache-Control: private, community="UCI" | ||
6488 | |||
6489 | A cache seeing this header field will act correctly even if the cache | ||
6490 | does not understand the community cache-extension, since it will also | ||
6491 | see and understand the private directive and thus default to the safe | ||
6492 | behavior. | ||
6493 | |||
6494 | |||
6495 | |||
6496 | |||
6497 | |||
6498 | Fielding, et al. Standards Track [Page 116] | ||
6499 | |||
6500 | RFC 2616 HTTP/1.1 June 1999 | ||
6501 | |||
6502 | |||
6503 | Unrecognized cache-directives MUST be ignored; it is assumed that any | ||
6504 | cache-directive likely to be unrecognized by an HTTP/1.1 cache will | ||
6505 | be combined with standard directives (or the response's default | ||
6506 | cacheability) such that the cache behavior will remain minimally | ||
6507 | correct even if the cache does not understand the extension(s). | ||
6508 | |||
6509 | 14.10 Connection | ||
6510 | |||
6511 | The Connection general-header field allows the sender to specify | ||
6512 | options that are desired for that particular connection and MUST NOT | ||
6513 | be communicated by proxies over further connections. | ||
6514 | |||
6515 | The Connection header has the following grammar: | ||
6516 | |||
6517 | Connection = "Connection" ":" 1#(connection-token) | ||
6518 | connection-token = token | ||
6519 | |||
6520 | HTTP/1.1 proxies MUST parse the Connection header field before a | ||
6521 | message is forwarded and, for each connection-token in this field, | ||
6522 | remove any header field(s) from the message with the same name as the | ||
6523 | connection-token. Connection options are signaled by the presence of | ||
6524 | a connection-token in the Connection header field, not by any | ||
6525 | corresponding additional header field(s), since the additional header | ||
6526 | field may not be sent if there are no parameters associated with that | ||
6527 | connection option. | ||
6528 | |||
6529 | Message headers listed in the Connection header MUST NOT include | ||
6530 | end-to-end headers, such as Cache-Control. | ||
6531 | |||
6532 | HTTP/1.1 defines the "close" connection option for the sender to | ||
6533 | signal that the connection will be closed after completion of the | ||
6534 | response. For example, | ||
6535 | |||
6536 | Connection: close | ||
6537 | |||
6538 | in either the request or the response header fields indicates that | ||
6539 | the connection SHOULD NOT be considered `persistent' (section 8.1) | ||
6540 | after the current request/response is complete. | ||
6541 | |||
6542 | HTTP/1.1 applications that do not support persistent connections MUST | ||
6543 | include the "close" connection option in every message. | ||
6544 | |||
6545 | A system receiving an HTTP/1.0 (or lower-version) message that | ||
6546 | includes a Connection header MUST, for each connection-token in this | ||
6547 | field, remove and ignore any header field(s) from the message with | ||
6548 | the same name as the connection-token. This protects against mistaken | ||
6549 | forwarding of such header fields by pre-HTTP/1.1 proxies. See section | ||
6550 | 19.6.2. | ||
6551 | |||
6552 | |||
6553 | |||
6554 | Fielding, et al. Standards Track [Page 117] | ||
6555 | |||
6556 | RFC 2616 HTTP/1.1 June 1999 | ||
6557 | |||
6558 | |||
6559 | 14.11 Content-Encoding | ||
6560 | |||
6561 | The Content-Encoding entity-header field is used as a modifier to the | ||
6562 | media-type. When present, its value indicates what additional content | ||
6563 | codings have been applied to the entity-body, and thus what decoding | ||
6564 | mechanisms must be applied in order to obtain the media-type | ||
6565 | referenced by the Content-Type header field. Content-Encoding is | ||
6566 | primarily used to allow a document to be compressed without losing | ||
6567 | the identity of its underlying media type. | ||
6568 | |||
6569 | Content-Encoding = "Content-Encoding" ":" 1#content-coding | ||
6570 | |||
6571 | Content codings are defined in section 3.5. An example of its use is | ||
6572 | |||
6573 | Content-Encoding: gzip | ||
6574 | |||
6575 | The content-coding is a characteristic of the entity identified by | ||
6576 | the Request-URI. Typically, the entity-body is stored with this | ||
6577 | encoding and is only decoded before rendering or analogous usage. | ||
6578 | However, a non-transparent proxy MAY modify the content-coding if the | ||
6579 | new coding is known to be acceptable to the recipient, unless the | ||
6580 | "no-transform" cache-control directive is present in the message. | ||
6581 | |||
6582 | If the content-coding of an entity is not "identity", then the | ||
6583 | response MUST include a Content-Encoding entity-header (section | ||
6584 | 14.11) that lists the non-identity content-coding(s) used. | ||
6585 | |||
6586 | If the content-coding of an entity in a request message is not | ||
6587 | acceptable to the origin server, the server SHOULD respond with a | ||
6588 | status code of 415 (Unsupported Media Type). | ||
6589 | |||
6590 | If multiple encodings have been applied to an entity, the content | ||
6591 | codings MUST be listed in the order in which they were applied. | ||
6592 | Additional information about the encoding parameters MAY be provided | ||
6593 | by other entity-header fields not defined by this specification. | ||
6594 | |||
6595 | 14.12 Content-Language | ||
6596 | |||
6597 | The Content-Language entity-header field describes the natural | ||
6598 | language(s) of the intended audience for the enclosed entity. Note | ||
6599 | that this might not be equivalent to all the languages used within | ||
6600 | the entity-body. | ||
6601 | |||
6602 | Content-Language = "Content-Language" ":" 1#language-tag | ||
6603 | |||
6604 | |||
6605 | |||
6606 | |||
6607 | |||
6608 | |||
6609 | |||
6610 | Fielding, et al. Standards Track [Page 118] | ||
6611 | |||
6612 | RFC 2616 HTTP/1.1 June 1999 | ||
6613 | |||
6614 | |||
6615 | Language tags are defined in section 3.10. The primary purpose of | ||
6616 | Content-Language is to allow a user to identify and differentiate | ||
6617 | entities according to the user's own preferred language. Thus, if the | ||
6618 | body content is intended only for a Danish-literate audience, the | ||
6619 | appropriate field is | ||
6620 | |||
6621 | Content-Language: da | ||
6622 | |||
6623 | If no Content-Language is specified, the default is that the content | ||
6624 | is intended for all language audiences. This might mean that the | ||
6625 | sender does not consider it to be specific to any natural language, | ||
6626 | or that the sender does not know for which language it is intended. | ||
6627 | |||
6628 | Multiple languages MAY be listed for content that is intended for | ||
6629 | multiple audiences. For example, a rendition of the "Treaty of | ||
6630 | Waitangi," presented simultaneously in the original Maori and English | ||
6631 | versions, would call for | ||
6632 | |||
6633 | Content-Language: mi, en | ||
6634 | |||
6635 | However, just because multiple languages are present within an entity | ||
6636 | does not mean that it is intended for multiple linguistic audiences. | ||
6637 | An example would be a beginner's language primer, such as "A First | ||
6638 | Lesson in Latin," which is clearly intended to be used by an | ||
6639 | English-literate audience. In this case, the Content-Language would | ||
6640 | properly only include "en". | ||
6641 | |||
6642 | Content-Language MAY be applied to any media type -- it is not | ||
6643 | limited to textual documents. | ||
6644 | |||
6645 | 14.13 Content-Length | ||
6646 | |||
6647 | The Content-Length entity-header field indicates the size of the | ||
6648 | entity-body, in decimal number of OCTETs, sent to the recipient or, | ||
6649 | in the case of the HEAD method, the size of the entity-body that | ||
6650 | would have been sent had the request been a GET. | ||
6651 | |||
6652 | Content-Length = "Content-Length" ":" 1*DIGIT | ||
6653 | |||
6654 | An example is | ||
6655 | |||
6656 | Content-Length: 3495 | ||
6657 | |||
6658 | Applications SHOULD use this field to indicate the transfer-length of | ||
6659 | the message-body, unless this is prohibited by the rules in section | ||
6660 | 4.4. | ||
6661 | |||
6662 | |||
6663 | |||
6664 | |||
6665 | |||
6666 | Fielding, et al. Standards Track [Page 119] | ||
6667 | |||
6668 | RFC 2616 HTTP/1.1 June 1999 | ||
6669 | |||
6670 | |||
6671 | Any Content-Length greater than or equal to zero is a valid value. | ||
6672 | Section 4.4 describes how to determine the length of a message-body | ||
6673 | if a Content-Length is not given. | ||
6674 | |||
6675 | Note that the meaning of this field is significantly different from | ||
6676 | the corresponding definition in MIME, where it is an optional field | ||
6677 | used within the "message/external-body" content-type. In HTTP, it | ||
6678 | SHOULD be sent whenever the message's length can be determined prior | ||
6679 | to being transferred, unless this is prohibited by the rules in | ||
6680 | section 4.4. | ||
6681 | |||
6682 | 14.14 Content-Location | ||
6683 | |||
6684 | The Content-Location entity-header field MAY be used to supply the | ||
6685 | resource location for the entity enclosed in the message when that | ||
6686 | entity is accessible from a location separate from the requested | ||
6687 | resource's URI. A server SHOULD provide a Content-Location for the | ||
6688 | variant corresponding to the response entity; especially in the case | ||
6689 | where a resource has multiple entities associated with it, and those | ||
6690 | entities actually have separate locations by which they might be | ||
6691 | individually accessed, the server SHOULD provide a Content-Location | ||
6692 | for the particular variant which is returned. | ||
6693 | |||
6694 | Content-Location = "Content-Location" ":" | ||
6695 | ( absoluteURI | relativeURI ) | ||
6696 | |||
6697 | The value of Content-Location also defines the base URI for the | ||
6698 | entity. | ||
6699 | |||
6700 | The Content-Location value is not a replacement for the original | ||
6701 | requested URI; it is only a statement of the location of the resource | ||
6702 | corresponding to this particular entity at the time of the request. | ||
6703 | Future requests MAY specify the Content-Location URI as the request- | ||
6704 | URI if the desire is to identify the source of that particular | ||
6705 | entity. | ||
6706 | |||
6707 | A cache cannot assume that an entity with a Content-Location | ||
6708 | different from the URI used to retrieve it can be used to respond to | ||
6709 | later requests on that Content-Location URI. However, the Content- | ||
6710 | Location can be used to differentiate between multiple entities | ||
6711 | retrieved from a single requested resource, as described in section | ||
6712 | 13.6. | ||
6713 | |||
6714 | If the Content-Location is a relative URI, the relative URI is | ||
6715 | interpreted relative to the Request-URI. | ||
6716 | |||
6717 | The meaning of the Content-Location header in PUT or POST requests is | ||
6718 | undefined; servers are free to ignore it in those cases. | ||
6719 | |||
6720 | |||
6721 | |||
6722 | Fielding, et al. Standards Track [Page 120] | ||
6723 | |||
6724 | RFC 2616 HTTP/1.1 June 1999 | ||
6725 | |||
6726 | |||
6727 | 14.15 Content-MD5 | ||
6728 | |||
6729 | The Content-MD5 entity-header field, as defined in RFC 1864 [23], is | ||
6730 | an MD5 digest of the entity-body for the purpose of providing an | ||
6731 | end-to-end message integrity check (MIC) of the entity-body. (Note: a | ||
6732 | MIC is good for detecting accidental modification of the entity-body | ||
6733 | in transit, but is not proof against malicious attacks.) | ||
6734 | |||
6735 | Content-MD5 = "Content-MD5" ":" md5-digest | ||
6736 | md5-digest = <base64 of 128 bit MD5 digest as per RFC 1864> | ||
6737 | |||
6738 | The Content-MD5 header field MAY be generated by an origin server or | ||
6739 | client to function as an integrity check of the entity-body. Only | ||
6740 | origin servers or clients MAY generate the Content-MD5 header field; | ||
6741 | proxies and gateways MUST NOT generate it, as this would defeat its | ||
6742 | value as an end-to-end integrity check. Any recipient of the entity- | ||
6743 | body, including gateways and proxies, MAY check that the digest value | ||
6744 | in this header field matches that of the entity-body as received. | ||
6745 | |||
6746 | The MD5 digest is computed based on the content of the entity-body, | ||
6747 | including any content-coding that has been applied, but not including | ||
6748 | any transfer-encoding applied to the message-body. If the message is | ||
6749 | received with a transfer-encoding, that encoding MUST be removed | ||
6750 | prior to checking the Content-MD5 value against the received entity. | ||
6751 | |||
6752 | This has the result that the digest is computed on the octets of the | ||
6753 | entity-body exactly as, and in the order that, they would be sent if | ||
6754 | no transfer-encoding were being applied. | ||
6755 | |||
6756 | HTTP extends RFC 1864 to permit the digest to be computed for MIME | ||
6757 | composite media-types (e.g., multipart/* and message/rfc822), but | ||
6758 | this does not change how the digest is computed as defined in the | ||
6759 | preceding paragraph. | ||
6760 | |||
6761 | There are several consequences of this. The entity-body for composite | ||
6762 | types MAY contain many body-parts, each with its own MIME and HTTP | ||
6763 | headers (including Content-MD5, Content-Transfer-Encoding, and | ||
6764 | Content-Encoding headers). If a body-part has a Content-Transfer- | ||
6765 | Encoding or Content-Encoding header, it is assumed that the content | ||
6766 | of the body-part has had the encoding applied, and the body-part is | ||
6767 | included in the Content-MD5 digest as is -- i.e., after the | ||
6768 | application. The Transfer-Encoding header field is not allowed within | ||
6769 | body-parts. | ||
6770 | |||
6771 | Conversion of all line breaks to CRLF MUST NOT be done before | ||
6772 | computing or checking the digest: the line break convention used in | ||
6773 | the text actually transmitted MUST be left unaltered when computing | ||
6774 | the digest. | ||
6775 | |||
6776 | |||
6777 | |||
6778 | Fielding, et al. Standards Track [Page 121] | ||
6779 | |||
6780 | RFC 2616 HTTP/1.1 June 1999 | ||
6781 | |||
6782 | |||
6783 | Note: while the definition of Content-MD5 is exactly the same for | ||
6784 | HTTP as in RFC 1864 for MIME entity-bodies, there are several ways | ||
6785 | in which the application of Content-MD5 to HTTP entity-bodies | ||
6786 | differs from its application to MIME entity-bodies. One is that | ||
6787 | HTTP, unlike MIME, does not use Content-Transfer-Encoding, and | ||
6788 | does use Transfer-Encoding and Content-Encoding. Another is that | ||
6789 | HTTP more frequently uses binary content types than MIME, so it is | ||
6790 | worth noting that, in such cases, the byte order used to compute | ||
6791 | the digest is the transmission byte order defined for the type. | ||
6792 | Lastly, HTTP allows transmission of text types with any of several | ||
6793 | line break conventions and not just the canonical form using CRLF. | ||
6794 | |||
6795 | 14.16 Content-Range | ||
6796 | |||
6797 | The Content-Range entity-header is sent with a partial entity-body to | ||
6798 | specify where in the full entity-body the partial body should be | ||
6799 | applied. Range units are defined in section 3.12. | ||
6800 | |||
6801 | Content-Range = "Content-Range" ":" content-range-spec | ||
6802 | |||
6803 | content-range-spec = byte-content-range-spec | ||
6804 | byte-content-range-spec = bytes-unit SP | ||
6805 | byte-range-resp-spec "/" | ||
6806 | ( instance-length | "*" ) | ||
6807 | |||
6808 | byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | ||
6809 | | "*" | ||
6810 | instance-length = 1*DIGIT | ||
6811 | |||
6812 | The header SHOULD indicate the total length of the full entity-body, | ||
6813 | unless this length is unknown or difficult to determine. The asterisk | ||
6814 | "*" character means that the instance-length is unknown at the time | ||
6815 | when the response was generated. | ||
6816 | |||
6817 | Unlike byte-ranges-specifier values (see section 14.35.1), a byte- | ||
6818 | range-resp-spec MUST only specify one range, and MUST contain | ||
6819 | absolute byte positions for both the first and last byte of the | ||
6820 | range. | ||
6821 | |||
6822 | A byte-content-range-spec with a byte-range-resp-spec whose last- | ||
6823 | byte-pos value is less than its first-byte-pos value, or whose | ||
6824 | instance-length value is less than or equal to its last-byte-pos | ||
6825 | value, is invalid. The recipient of an invalid byte-content-range- | ||
6826 | spec MUST ignore it and any content transferred along with it. | ||
6827 | |||
6828 | A server sending a response with status code 416 (Requested range not | ||
6829 | satisfiable) SHOULD include a Content-Range field with a byte-range- | ||
6830 | resp-spec of "*". The instance-length specifies the current length of | ||
6831 | |||
6832 | |||
6833 | |||
6834 | Fielding, et al. Standards Track [Page 122] | ||
6835 | |||
6836 | RFC 2616 HTTP/1.1 June 1999 | ||
6837 | |||
6838 | |||
6839 | the selected resource. A response with status code 206 (Partial | ||
6840 | Content) MUST NOT include a Content-Range field with a byte-range- | ||
6841 | resp-spec of "*". | ||
6842 | |||
6843 | Examples of byte-content-range-spec values, assuming that the entity | ||
6844 | contains a total of 1234 bytes: | ||
6845 | |||
6846 | . The first 500 bytes: | ||
6847 | bytes 0-499/1234 | ||
6848 | |||
6849 | . The second 500 bytes: | ||
6850 | bytes 500-999/1234 | ||
6851 | |||
6852 | . All except for the first 500 bytes: | ||
6853 | bytes 500-1233/1234 | ||
6854 | |||
6855 | . The last 500 bytes: | ||
6856 | bytes 734-1233/1234 | ||
6857 | |||
6858 | When an HTTP message includes the content of a single range (for | ||
6859 | example, a response to a request for a single range, or to a request | ||
6860 | for a set of ranges that overlap without any holes), this content is | ||
6861 | transmitted with a Content-Range header, and a Content-Length header | ||
6862 | showing the number of bytes actually transferred. For example, | ||
6863 | |||
6864 | HTTP/1.1 206 Partial content | ||
6865 | Date: Wed, 15 Nov 1995 06:25:24 GMT | ||
6866 | Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT | ||
6867 | Content-Range: bytes 21010-47021/47022 | ||
6868 | Content-Length: 26012 | ||
6869 | Content-Type: image/gif | ||
6870 | |||
6871 | When an HTTP message includes the content of multiple ranges (for | ||
6872 | example, a response to a request for multiple non-overlapping | ||
6873 | ranges), these are transmitted as a multipart message. The multipart | ||
6874 | media type used for this purpose is "multipart/byteranges" as defined | ||
6875 | in appendix 19.2. See appendix 19.6.3 for a compatibility issue. | ||
6876 | |||
6877 | A response to a request for a single range MUST NOT be sent using the | ||
6878 | multipart/byteranges media type. A response to a request for | ||
6879 | multiple ranges, whose result is a single range, MAY be sent as a | ||
6880 | multipart/byteranges media type with one part. A client that cannot | ||
6881 | decode a multipart/byteranges message MUST NOT ask for multiple | ||
6882 | byte-ranges in a single request. | ||
6883 | |||
6884 | When a client requests multiple byte-ranges in one request, the | ||
6885 | server SHOULD return them in the order that they appeared in the | ||
6886 | request. | ||
6887 | |||
6888 | |||
6889 | |||
6890 | Fielding, et al. Standards Track [Page 123] | ||
6891 | |||
6892 | RFC 2616 HTTP/1.1 June 1999 | ||
6893 | |||
6894 | |||
6895 | If the server ignores a byte-range-spec because it is syntactically | ||
6896 | invalid, the server SHOULD treat the request as if the invalid Range | ||
6897 | header field did not exist. (Normally, this means return a 200 | ||
6898 | response containing the full entity). | ||
6899 | |||
6900 | If the server receives a request (other than one including an If- | ||
6901 | Range request-header field) with an unsatisfiable Range request- | ||
6902 | header field (that is, all of whose byte-range-spec values have a | ||
6903 | first-byte-pos value greater than the current length of the selected | ||
6904 | resource), it SHOULD return a response code of 416 (Requested range | ||
6905 | not satisfiable) (section 10.4.17). | ||
6906 | |||
6907 | Note: clients cannot depend on servers to send a 416 (Requested | ||
6908 | range not satisfiable) response instead of a 200 (OK) response for | ||
6909 | an unsatisfiable Range request-header, since not all servers | ||
6910 | implement this request-header. | ||
6911 | |||
6912 | 14.17 Content-Type | ||
6913 | |||
6914 | The Content-Type entity-header field indicates the media type of the | ||
6915 | entity-body sent to the recipient or, in the case of the HEAD method, | ||
6916 | the media type that would have been sent had the request been a GET. | ||
6917 | |||
6918 | Content-Type = "Content-Type" ":" media-type | ||
6919 | |||
6920 | Media types are defined in section 3.7. An example of the field is | ||
6921 | |||
6922 | Content-Type: text/html; charset=ISO-8859-4 | ||
6923 | |||
6924 | Further discussion of methods for identifying the media type of an | ||
6925 | entity is provided in section 7.2.1. | ||
6926 | |||
6927 | 14.18 Date | ||
6928 | |||
6929 | The Date general-header field represents the date and time at which | ||
6930 | the message was originated, having the same semantics as orig-date in | ||
6931 | RFC 822. The field value is an HTTP-date, as described in section | ||
6932 | 3.3.1; it MUST be sent in RFC 1123 [8]-date format. | ||
6933 | |||
6934 | Date = "Date" ":" HTTP-date | ||
6935 | |||
6936 | An example is | ||
6937 | |||
6938 | Date: Tue, 15 Nov 1994 08:12:31 GMT | ||
6939 | |||
6940 | Origin servers MUST include a Date header field in all responses, | ||
6941 | except in these cases: | ||
6942 | |||
6943 | |||
6944 | |||
6945 | |||
6946 | Fielding, et al. Standards Track [Page 124] | ||
6947 | |||
6948 | RFC 2616 HTTP/1.1 June 1999 | ||
6949 | |||
6950 | |||
6951 | 1. If the response status code is 100 (Continue) or 101 (Switching | ||
6952 | Protocols), the response MAY include a Date header field, at | ||
6953 | the server's option. | ||
6954 | |||
6955 | 2. If the response status code conveys a server error, e.g. 500 | ||
6956 | (Internal Server Error) or 503 (Service Unavailable), and it is | ||
6957 | inconvenient or impossible to generate a valid Date. | ||
6958 | |||
6959 | 3. If the server does not have a clock that can provide a | ||
6960 | reasonable approximation of the current time, its responses | ||
6961 | MUST NOT include a Date header field. In this case, the rules | ||
6962 | in section 14.18.1 MUST be followed. | ||
6963 | |||
6964 | A received message that does not have a Date header field MUST be | ||
6965 | assigned one by the recipient if the message will be cached by that | ||
6966 | recipient or gatewayed via a protocol which requires a Date. An HTTP | ||
6967 | implementation without a clock MUST NOT cache responses without | ||
6968 | revalidating them on every use. An HTTP cache, especially a shared | ||
6969 | cache, SHOULD use a mechanism, such as NTP [28], to synchronize its | ||
6970 | clock with a reliable external standard. | ||
6971 | |||
6972 | Clients SHOULD only send a Date header field in messages that include | ||
6973 | an entity-body, as in the case of the PUT and POST requests, and even | ||
6974 | then it is optional. A client without a clock MUST NOT send a Date | ||
6975 | header field in a request. | ||
6976 | |||
6977 | The HTTP-date sent in a Date header SHOULD NOT represent a date and | ||
6978 | time subsequent to the generation of the message. It SHOULD represent | ||
6979 | the best available approximation of the date and time of message | ||
6980 | generation, unless the implementation has no means of generating a | ||
6981 | reasonably accurate date and time. In theory, the date ought to | ||
6982 | represent the moment just before the entity is generated. In | ||
6983 | practice, the date can be generated at any time during the message | ||
6984 | origination without affecting its semantic value. | ||
6985 | |||
6986 | 14.18.1 Clockless Origin Server Operation | ||
6987 | |||
6988 | Some origin server implementations might not have a clock available. | ||
6989 | An origin server without a clock MUST NOT assign Expires or Last- | ||
6990 | Modified values to a response, unless these values were associated | ||
6991 | with the resource by a system or user with a reliable clock. It MAY | ||
6992 | assign an Expires value that is known, at or before server | ||
6993 | configuration time, to be in the past (this allows "pre-expiration" | ||
6994 | of responses without storing separate Expires values for each | ||
6995 | resource). | ||
6996 | |||
6997 | |||
6998 | |||
6999 | |||
7000 | |||
7001 | |||
7002 | Fielding, et al. Standards Track [Page 125] | ||
7003 | |||
7004 | RFC 2616 HTTP/1.1 June 1999 | ||
7005 | |||
7006 | |||
7007 | 14.19 ETag | ||
7008 | |||
7009 | The ETag response-header field provides the current value of the | ||
7010 | entity tag for the requested variant. The headers used with entity | ||
7011 | tags are described in sections 14.24, 14.26 and 14.44. The entity tag | ||
7012 | MAY be used for comparison with other entities from the same resource | ||
7013 | (see section 13.3.3). | ||
7014 | |||
7015 | ETag = "ETag" ":" entity-tag | ||
7016 | |||
7017 | Examples: | ||
7018 | |||
7019 | ETag: "xyzzy" | ||
7020 | ETag: W/"xyzzy" | ||
7021 | ETag: "" | ||
7022 | |||
7023 | 14.20 Expect | ||
7024 | |||
7025 | The Expect request-header field is used to indicate that particular | ||
7026 | server behaviors are required by the client. | ||
7027 | |||
7028 | Expect = "Expect" ":" 1#expectation | ||
7029 | |||
7030 | expectation = "100-continue" | expectation-extension | ||
7031 | expectation-extension = token [ "=" ( token | quoted-string ) | ||
7032 | *expect-params ] | ||
7033 | expect-params = ";" token [ "=" ( token | quoted-string ) ] | ||
7034 | |||
7035 | |||
7036 | A server that does not understand or is unable to comply with any of | ||
7037 | the expectation values in the Expect field of a request MUST respond | ||
7038 | with appropriate error status. The server MUST respond with a 417 | ||
7039 | (Expectation Failed) status if any of the expectations cannot be met | ||
7040 | or, if there are other problems with the request, some other 4xx | ||
7041 | status. | ||
7042 | |||
7043 | This header field is defined with extensible syntax to allow for | ||
7044 | future extensions. If a server receives a request containing an | ||
7045 | Expect field that includes an expectation-extension that it does not | ||
7046 | support, it MUST respond with a 417 (Expectation Failed) status. | ||
7047 | |||
7048 | Comparison of expectation values is case-insensitive for unquoted | ||
7049 | tokens (including the 100-continue token), and is case-sensitive for | ||
7050 | quoted-string expectation-extensions. | ||
7051 | |||
7052 | |||
7053 | |||
7054 | |||
7055 | |||
7056 | |||
7057 | |||
7058 | Fielding, et al. Standards Track [Page 126] | ||
7059 | |||
7060 | RFC 2616 HTTP/1.1 June 1999 | ||
7061 | |||
7062 | |||
7063 | The Expect mechanism is hop-by-hop: that is, an HTTP/1.1 proxy MUST | ||
7064 | return a 417 (Expectation Failed) status if it receives a request | ||
7065 | with an expectation that it cannot meet. However, the Expect | ||
7066 | request-header itself is end-to-end; it MUST be forwarded if the | ||
7067 | request is forwarded. | ||
7068 | |||
7069 | Many older HTTP/1.0 and HTTP/1.1 applications do not understand the | ||
7070 | Expect header. | ||
7071 | |||
7072 | See section 8.2.3 for the use of the 100 (continue) status. | ||
7073 | |||
7074 | 14.21 Expires | ||
7075 | |||
7076 | The Expires entity-header field gives the date/time after which the | ||
7077 | response is considered stale. A stale cache entry may not normally be | ||
7078 | returned by a cache (either a proxy cache or a user agent cache) | ||
7079 | unless it is first validated with the origin server (or with an | ||
7080 | intermediate cache that has a fresh copy of the entity). See section | ||
7081 | 13.2 for further discussion of the expiration model. | ||
7082 | |||
7083 | The presence of an Expires field does not imply that the original | ||
7084 | resource will change or cease to exist at, before, or after that | ||
7085 | time. | ||
7086 | |||
7087 | The format is an absolute date and time as defined by HTTP-date in | ||
7088 | section 3.3.1; it MUST be in RFC 1123 date format: | ||
7089 | |||
7090 | Expires = "Expires" ":" HTTP-date | ||
7091 | |||
7092 | An example of its use is | ||
7093 | |||
7094 | Expires: Thu, 01 Dec 1994 16:00:00 GMT | ||
7095 | |||
7096 | Note: if a response includes a Cache-Control field with the max- | ||
7097 | age directive (see section 14.9.3), that directive overrides the | ||
7098 | Expires field. | ||
7099 | |||
7100 | HTTP/1.1 clients and caches MUST treat other invalid date formats, | ||
7101 | especially including the value "0", as in the past (i.e., "already | ||
7102 | expired"). | ||
7103 | |||
7104 | To mark a response as "already expired," an origin server sends an | ||
7105 | Expires date that is equal to the Date header value. (See the rules | ||
7106 | for expiration calculations in section 13.2.4.) | ||
7107 | |||
7108 | |||
7109 | |||
7110 | |||
7111 | |||
7112 | |||
7113 | |||
7114 | Fielding, et al. Standards Track [Page 127] | ||
7115 | |||
7116 | RFC 2616 HTTP/1.1 June 1999 | ||
7117 | |||
7118 | |||
7119 | To mark a response as "never expires," an origin server sends an | ||
7120 | Expires date approximately one year from the time the response is | ||
7121 | sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one | ||
7122 | year in the future. | ||
7123 | |||
7124 | The presence of an Expires header field with a date value of some | ||
7125 | time in the future on a response that otherwise would by default be | ||
7126 | non-cacheable indicates that the response is cacheable, unless | ||
7127 | indicated otherwise by a Cache-Control header field (section 14.9). | ||
7128 | |||
7129 | 14.22 From | ||
7130 | |||
7131 | The From request-header field, if given, SHOULD contain an Internet | ||
7132 | e-mail address for the human user who controls the requesting user | ||
7133 | agent. The address SHOULD be machine-usable, as defined by "mailbox" | ||
7134 | in RFC 822 [9] as updated by RFC 1123 [8]: | ||
7135 | |||
7136 | From = "From" ":" mailbox | ||
7137 | |||
7138 | An example is: | ||
7139 | |||
7140 | From: webmaster@w3.org | ||
7141 | |||
7142 | This header field MAY be used for logging purposes and as a means for | ||
7143 | identifying the source of invalid or unwanted requests. It SHOULD NOT | ||
7144 | be used as an insecure form of access protection. The interpretation | ||
7145 | of this field is that the request is being performed on behalf of the | ||
7146 | person given, who accepts responsibility for the method performed. In | ||
7147 | particular, robot agents SHOULD include this header so that the | ||
7148 | person responsible for running the robot can be contacted if problems | ||
7149 | occur on the receiving end. | ||
7150 | |||
7151 | The Internet e-mail address in this field MAY be separate from the | ||
7152 | Internet host which issued the request. For example, when a request | ||
7153 | is passed through a proxy the original issuer's address SHOULD be | ||
7154 | used. | ||
7155 | |||
7156 | The client SHOULD NOT send the From header field without the user's | ||
7157 | approval, as it might conflict with the user's privacy interests or | ||
7158 | their site's security policy. It is strongly recommended that the | ||
7159 | user be able to disable, enable, and modify the value of this field | ||
7160 | at any time prior to a request. | ||
7161 | |||
7162 | 14.23 Host | ||
7163 | |||
7164 | The Host request-header field specifies the Internet host and port | ||
7165 | number of the resource being requested, as obtained from the original | ||
7166 | URI given by the user or referring resource (generally an HTTP URL, | ||
7167 | |||
7168 | |||
7169 | |||
7170 | Fielding, et al. Standards Track [Page 128] | ||
7171 | |||
7172 | RFC 2616 HTTP/1.1 June 1999 | ||
7173 | |||
7174 | |||
7175 | as described in section 3.2.2). The Host field value MUST represent | ||
7176 | the naming authority of the origin server or gateway given by the | ||
7177 | original URL. This allows the origin server or gateway to | ||
7178 | differentiate between internally-ambiguous URLs, such as the root "/" | ||
7179 | URL of a server for multiple host names on a single IP address. | ||
7180 | |||
7181 | Host = "Host" ":" host [ ":" port ] ; Section 3.2.2 | ||
7182 | |||
7183 | A "host" without any trailing port information implies the default | ||
7184 | port for the service requested (e.g., "80" for an HTTP URL). For | ||
7185 | example, a request on the origin server for | ||
7186 | <http://www.w3.org/pub/WWW/> would properly include: | ||
7187 | |||
7188 | GET /pub/WWW/ HTTP/1.1 | ||
7189 | Host: www.w3.org | ||
7190 | |||
7191 | A client MUST include a Host header field in all HTTP/1.1 request | ||
7192 | messages . If the requested URI does not include an Internet host | ||
7193 | name for the service being requested, then the Host header field MUST | ||
7194 | be given with an empty value. An HTTP/1.1 proxy MUST ensure that any | ||
7195 | request message it forwards does contain an appropriate Host header | ||
7196 | field that identifies the service being requested by the proxy. All | ||
7197 | Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) | ||
7198 | status code to any HTTP/1.1 request message which lacks a Host header | ||
7199 | field. | ||
7200 | |||
7201 | See sections 5.2 and 19.6.1.1 for other requirements relating to | ||
7202 | Host. | ||
7203 | |||
7204 | 14.24 If-Match | ||
7205 | |||
7206 | The If-Match request-header field is used with a method to make it | ||
7207 | conditional. A client that has one or more entities previously | ||
7208 | obtained from the resource can verify that one of those entities is | ||
7209 | current by including a list of their associated entity tags in the | ||
7210 | If-Match header field. Entity tags are defined in section 3.11. The | ||
7211 | purpose of this feature is to allow efficient updates of cached | ||
7212 | information with a minimum amount of transaction overhead. It is also | ||
7213 | used, on updating requests, to prevent inadvertent modification of | ||
7214 | the wrong version of a resource. As a special case, the value "*" | ||
7215 | matches any current entity of the resource. | ||
7216 | |||
7217 | If-Match = "If-Match" ":" ( "*" | 1#entity-tag ) | ||
7218 | |||
7219 | If any of the entity tags match the entity tag of the entity that | ||
7220 | would have been returned in the response to a similar GET request | ||
7221 | (without the If-Match header) on that resource, or if "*" is given | ||
7222 | |||
7223 | |||
7224 | |||
7225 | |||
7226 | Fielding, et al. Standards Track [Page 129] | ||
7227 | |||
7228 | RFC 2616 HTTP/1.1 June 1999 | ||
7229 | |||
7230 | |||
7231 | and any current entity exists for that resource, then the server MAY | ||
7232 | perform the requested method as if the If-Match header field did not | ||
7233 | exist. | ||
7234 | |||
7235 | A server MUST use the strong comparison function (see section 13.3.3) | ||
7236 | to compare the entity tags in If-Match. | ||
7237 | |||
7238 | If none of the entity tags match, or if "*" is given and no current | ||
7239 | entity exists, the server MUST NOT perform the requested method, and | ||
7240 | MUST return a 412 (Precondition Failed) response. This behavior is | ||
7241 | most useful when the client wants to prevent an updating method, such | ||
7242 | as PUT, from modifying a resource that has changed since the client | ||
7243 | last retrieved it. | ||
7244 | |||
7245 | If the request would, without the If-Match header field, result in | ||
7246 | anything other than a 2xx or 412 status, then the If-Match header | ||
7247 | MUST be ignored. | ||
7248 | |||
7249 | The meaning of "If-Match: *" is that the method SHOULD be performed | ||
7250 | if the representation selected by the origin server (or by a cache, | ||
7251 | possibly using the Vary mechanism, see section 14.44) exists, and | ||
7252 | MUST NOT be performed if the representation does not exist. | ||
7253 | |||
7254 | A request intended to update a resource (e.g., a PUT) MAY include an | ||
7255 | If-Match header field to signal that the request method MUST NOT be | ||
7256 | applied if the entity corresponding to the If-Match value (a single | ||
7257 | entity tag) is no longer a representation of that resource. This | ||
7258 | allows the user to indicate that they do not wish the request to be | ||
7259 | successful if the resource has been changed without their knowledge. | ||
7260 | Examples: | ||
7261 | |||
7262 | If-Match: "xyzzy" | ||
7263 | If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" | ||
7264 | If-Match: * | ||
7265 | |||
7266 | The result of a request having both an If-Match header field and | ||
7267 | either an If-None-Match or an If-Modified-Since header fields is | ||
7268 | undefined by this specification. | ||
7269 | |||
7270 | 14.25 If-Modified-Since | ||
7271 | |||
7272 | The If-Modified-Since request-header field is used with a method to | ||
7273 | make it conditional: if the requested variant has not been modified | ||
7274 | since the time specified in this field, an entity will not be | ||
7275 | returned from the server; instead, a 304 (not modified) response will | ||
7276 | be returned without any message-body. | ||
7277 | |||
7278 | If-Modified-Since = "If-Modified-Since" ":" HTTP-date | ||
7279 | |||
7280 | |||
7281 | |||
7282 | Fielding, et al. Standards Track [Page 130] | ||
7283 | |||
7284 | RFC 2616 HTTP/1.1 June 1999 | ||
7285 | |||
7286 | |||
7287 | An example of the field is: | ||
7288 | |||
7289 | If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT | ||
7290 | |||
7291 | A GET method with an If-Modified-Since header and no Range header | ||
7292 | requests that the identified entity be transferred only if it has | ||
7293 | been modified since the date given by the If-Modified-Since header. | ||
7294 | The algorithm for determining this includes the following cases: | ||
7295 | |||
7296 | a) If the request would normally result in anything other than a | ||
7297 | 200 (OK) status, or if the passed If-Modified-Since date is | ||
7298 | invalid, the response is exactly the same as for a normal GET. | ||
7299 | A date which is later than the server's current time is | ||
7300 | invalid. | ||
7301 | |||
7302 | b) If the variant has been modified since the If-Modified-Since | ||
7303 | date, the response is exactly the same as for a normal GET. | ||
7304 | |||
7305 | c) If the variant has not been modified since a valid If- | ||
7306 | Modified-Since date, the server SHOULD return a 304 (Not | ||
7307 | Modified) response. | ||
7308 | |||
7309 | The purpose of this feature is to allow efficient updates of cached | ||
7310 | information with a minimum amount of transaction overhead. | ||
7311 | |||
7312 | Note: The Range request-header field modifies the meaning of If- | ||
7313 | Modified-Since; see section 14.35 for full details. | ||
7314 | |||
7315 | Note: If-Modified-Since times are interpreted by the server, whose | ||
7316 | clock might not be synchronized with the client. | ||
7317 | |||
7318 | Note: When handling an If-Modified-Since header field, some | ||
7319 | servers will use an exact date comparison function, rather than a | ||
7320 | less-than function, for deciding whether to send a 304 (Not | ||
7321 | Modified) response. To get best results when sending an If- | ||
7322 | Modified-Since header field for cache validation, clients are | ||
7323 | advised to use the exact date string received in a previous Last- | ||
7324 | Modified header field whenever possible. | ||
7325 | |||
7326 | Note: If a client uses an arbitrary date in the If-Modified-Since | ||
7327 | header instead of a date taken from the Last-Modified header for | ||
7328 | the same request, the client should be aware of the fact that this | ||
7329 | date is interpreted in the server's understanding of time. The | ||
7330 | client should consider unsynchronized clocks and rounding problems | ||
7331 | due to the different encodings of time between the client and | ||
7332 | server. This includes the possibility of race conditions if the | ||
7333 | document has changed between the time it was first requested and | ||
7334 | the If-Modified-Since date of a subsequent request, and the | ||
7335 | |||
7336 | |||
7337 | |||
7338 | Fielding, et al. Standards Track [Page 131] | ||
7339 | |||
7340 | RFC 2616 HTTP/1.1 June 1999 | ||
7341 | |||
7342 | |||
7343 | possibility of clock-skew-related problems if the If-Modified- | ||
7344 | Since date is derived from the client's clock without correction | ||
7345 | to the server's clock. Corrections for different time bases | ||
7346 | between client and server are at best approximate due to network | ||
7347 | latency. | ||
7348 | |||
7349 | The result of a request having both an If-Modified-Since header field | ||
7350 | and either an If-Match or an If-Unmodified-Since header fields is | ||
7351 | undefined by this specification. | ||
7352 | |||
7353 | 14.26 If-None-Match | ||
7354 | |||
7355 | The If-None-Match request-header field is used with a method to make | ||
7356 | it conditional. A client that has one or more entities previously | ||
7357 | obtained from the resource can verify that none of those entities is | ||
7358 | current by including a list of their associated entity tags in the | ||
7359 | If-None-Match header field. The purpose of this feature is to allow | ||
7360 | efficient updates of cached information with a minimum amount of | ||
7361 | transaction overhead. It is also used to prevent a method (e.g. PUT) | ||
7362 | from inadvertently modifying an existing resource when the client | ||
7363 | believes that the resource does not exist. | ||
7364 | |||
7365 | As a special case, the value "*" matches any current entity of the | ||
7366 | resource. | ||
7367 | |||
7368 | If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag ) | ||
7369 | |||
7370 | If any of the entity tags match the entity tag of the entity that | ||
7371 | would have been returned in the response to a similar GET request | ||
7372 | (without the If-None-Match header) on that resource, or if "*" is | ||
7373 | given and any current entity exists for that resource, then the | ||
7374 | server MUST NOT perform the requested method, unless required to do | ||
7375 | so because the resource's modification date fails to match that | ||
7376 | supplied in an If-Modified-Since header field in the request. | ||
7377 | Instead, if the request method was GET or HEAD, the server SHOULD | ||
7378 | respond with a 304 (Not Modified) response, including the cache- | ||
7379 | related header fields (particularly ETag) of one of the entities that | ||
7380 | matched. For all other request methods, the server MUST respond with | ||
7381 | a status of 412 (Precondition Failed). | ||
7382 | |||
7383 | See section 13.3.3 for rules on how to determine if two entities tags | ||
7384 | match. The weak comparison function can only be used with GET or HEAD | ||
7385 | requests. | ||
7386 | |||
7387 | |||
7388 | |||
7389 | |||
7390 | |||
7391 | |||
7392 | |||
7393 | |||
7394 | Fielding, et al. Standards Track [Page 132] | ||
7395 | |||
7396 | RFC 2616 HTTP/1.1 June 1999 | ||
7397 | |||
7398 | |||
7399 | If none of the entity tags match, then the server MAY perform the | ||
7400 | requested method as if the If-None-Match header field did not exist, | ||
7401 | but MUST also ignore any If-Modified-Since header field(s) in the | ||
7402 | request. That is, if no entity tags match, then the server MUST NOT | ||
7403 | return a 304 (Not Modified) response. | ||
7404 | |||
7405 | If the request would, without the If-None-Match header field, result | ||
7406 | in anything other than a 2xx or 304 status, then the If-None-Match | ||
7407 | header MUST be ignored. (See section 13.3.4 for a discussion of | ||
7408 | server behavior when both If-Modified-Since and If-None-Match appear | ||
7409 | in the same request.) | ||
7410 | |||
7411 | The meaning of "If-None-Match: *" is that the method MUST NOT be | ||
7412 | performed if the representation selected by the origin server (or by | ||
7413 | a cache, possibly using the Vary mechanism, see section 14.44) | ||
7414 | exists, and SHOULD be performed if the representation does not exist. | ||
7415 | This feature is intended to be useful in preventing races between PUT | ||
7416 | operations. | ||
7417 | |||
7418 | Examples: | ||
7419 | |||
7420 | If-None-Match: "xyzzy" | ||
7421 | If-None-Match: W/"xyzzy" | ||
7422 | If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" | ||
7423 | If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz" | ||
7424 | If-None-Match: * | ||
7425 | |||
7426 | The result of a request having both an If-None-Match header field and | ||
7427 | either an If-Match or an If-Unmodified-Since header fields is | ||
7428 | undefined by this specification. | ||
7429 | |||
7430 | 14.27 If-Range | ||
7431 | |||
7432 | If a client has a partial copy of an entity in its cache, and wishes | ||
7433 | to have an up-to-date copy of the entire entity in its cache, it | ||
7434 | could use the Range request-header with a conditional GET (using | ||
7435 | either or both of If-Unmodified-Since and If-Match.) However, if the | ||
7436 | condition fails because the entity has been modified, the client | ||
7437 | would then have to make a second request to obtain the entire current | ||
7438 | entity-body. | ||
7439 | |||
7440 | The If-Range header allows a client to "short-circuit" the second | ||
7441 | request. Informally, its meaning is `if the entity is unchanged, send | ||
7442 | me the part(s) that I am missing; otherwise, send me the entire new | ||
7443 | entity'. | ||
7444 | |||
7445 | If-Range = "If-Range" ":" ( entity-tag | HTTP-date ) | ||
7446 | |||
7447 | |||
7448 | |||
7449 | |||
7450 | Fielding, et al. Standards Track [Page 133] | ||
7451 | |||
7452 | RFC 2616 HTTP/1.1 June 1999 | ||
7453 | |||
7454 | |||
7455 | If the client has no entity tag for an entity, but does have a Last- | ||
7456 | Modified date, it MAY use that date in an If-Range header. (The | ||
7457 | server can distinguish between a valid HTTP-date and any form of | ||
7458 | entity-tag by examining no more than two characters.) The If-Range | ||
7459 | header SHOULD only be used together with a Range header, and MUST be | ||
7460 | ignored if the request does not include a Range header, or if the | ||
7461 | server does not support the sub-range operation. | ||
7462 | |||
7463 | If the entity tag given in the If-Range header matches the current | ||
7464 | entity tag for the entity, then the server SHOULD provide the | ||
7465 | specified sub-range of the entity using a 206 (Partial content) | ||
7466 | response. If the entity tag does not match, then the server SHOULD | ||
7467 | return the entire entity using a 200 (OK) response. | ||
7468 | |||
7469 | 14.28 If-Unmodified-Since | ||
7470 | |||
7471 | The If-Unmodified-Since request-header field is used with a method to | ||
7472 | make it conditional. If the requested resource has not been modified | ||
7473 | since the time specified in this field, the server SHOULD perform the | ||
7474 | requested operation as if the If-Unmodified-Since header were not | ||
7475 | present. | ||
7476 | |||
7477 | If the requested variant has been modified since the specified time, | ||
7478 | the server MUST NOT perform the requested operation, and MUST return | ||
7479 | a 412 (Precondition Failed). | ||
7480 | |||
7481 | If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date | ||
7482 | |||
7483 | An example of the field is: | ||
7484 | |||
7485 | If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT | ||
7486 | |||
7487 | If the request normally (i.e., without the If-Unmodified-Since | ||
7488 | header) would result in anything other than a 2xx or 412 status, the | ||
7489 | If-Unmodified-Since header SHOULD be ignored. | ||
7490 | |||
7491 | If the specified date is invalid, the header is ignored. | ||
7492 | |||
7493 | The result of a request having both an If-Unmodified-Since header | ||
7494 | field and either an If-None-Match or an If-Modified-Since header | ||
7495 | fields is undefined by this specification. | ||
7496 | |||
7497 | 14.29 Last-Modified | ||
7498 | |||
7499 | The Last-Modified entity-header field indicates the date and time at | ||
7500 | which the origin server believes the variant was last modified. | ||
7501 | |||
7502 | Last-Modified = "Last-Modified" ":" HTTP-date | ||
7503 | |||
7504 | |||
7505 | |||
7506 | Fielding, et al. Standards Track [Page 134] | ||
7507 | |||
7508 | RFC 2616 HTTP/1.1 June 1999 | ||
7509 | |||
7510 | |||
7511 | An example of its use is | ||
7512 | |||
7513 | Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT | ||
7514 | |||
7515 | The exact meaning of this header field depends on the implementation | ||
7516 | of the origin server and the nature of the original resource. For | ||
7517 | files, it may be just the file system last-modified time. For | ||
7518 | entities with dynamically included parts, it may be the most recent | ||
7519 | of the set of last-modify times for its component parts. For database | ||
7520 | gateways, it may be the last-update time stamp of the record. For | ||
7521 | virtual objects, it may be the last time the internal state changed. | ||
7522 | |||
7523 | An origin server MUST NOT send a Last-Modified date which is later | ||
7524 | than the server's time of message origination. In such cases, where | ||
7525 | the resource's last modification would indicate some time in the | ||
7526 | future, the server MUST replace that date with the message | ||
7527 | origination date. | ||
7528 | |||
7529 | An origin server SHOULD obtain the Last-Modified value of the entity | ||
7530 | as close as possible to the time that it generates the Date value of | ||
7531 | its response. This allows a recipient to make an accurate assessment | ||
7532 | of the entity's modification time, especially if the entity changes | ||
7533 | near the time that the response is generated. | ||
7534 | |||
7535 | HTTP/1.1 servers SHOULD send Last-Modified whenever feasible. | ||
7536 | |||
7537 | 14.30 Location | ||
7538 | |||
7539 | The Location response-header field is used to redirect the recipient | ||
7540 | to a location other than the Request-URI for completion of the | ||
7541 | request or identification of a new resource. For 201 (Created) | ||
7542 | responses, the Location is that of the new resource which was created | ||
7543 | by the request. For 3xx responses, the location SHOULD indicate the | ||
7544 | server's preferred URI for automatic redirection to the resource. The | ||
7545 | field value consists of a single absolute URI. | ||
7546 | |||
7547 | Location = "Location" ":" absoluteURI | ||
7548 | |||
7549 | An example is: | ||
7550 | |||
7551 | Location: http://www.w3.org/pub/WWW/People.html | ||
7552 | |||
7553 | Note: The Content-Location header field (section 14.14) differs | ||
7554 | from Location in that the Content-Location identifies the original | ||
7555 | location of the entity enclosed in the request. It is therefore | ||
7556 | possible for a response to contain header fields for both Location | ||
7557 | and Content-Location. Also see section 13.10 for cache | ||
7558 | requirements of some methods. | ||
7559 | |||
7560 | |||
7561 | |||
7562 | Fielding, et al. Standards Track [Page 135] | ||
7563 | |||
7564 | RFC 2616 HTTP/1.1 June 1999 | ||
7565 | |||
7566 | |||
7567 | 14.31 Max-Forwards | ||
7568 | |||
7569 | The Max-Forwards request-header field provides a mechanism with the | ||
7570 | TRACE (section 9.8) and OPTIONS (section 9.2) methods to limit the | ||
7571 | number of proxies or gateways that can forward the request to the | ||
7572 | next inbound server. This can be useful when the client is attempting | ||
7573 | to trace a request chain which appears to be failing or looping in | ||
7574 | mid-chain. | ||
7575 | |||
7576 | Max-Forwards = "Max-Forwards" ":" 1*DIGIT | ||
7577 | |||
7578 | The Max-Forwards value is a decimal integer indicating the remaining | ||
7579 | number of times this request message may be forwarded. | ||
7580 | |||
7581 | Each proxy or gateway recipient of a TRACE or OPTIONS request | ||
7582 | containing a Max-Forwards header field MUST check and update its | ||
7583 | value prior to forwarding the request. If the received value is zero | ||
7584 | (0), the recipient MUST NOT forward the request; instead, it MUST | ||
7585 | respond as the final recipient. If the received Max-Forwards value is | ||
7586 | greater than zero, then the forwarded message MUST contain an updated | ||
7587 | Max-Forwards field with a value decremented by one (1). | ||
7588 | |||
7589 | The Max-Forwards header field MAY be ignored for all other methods | ||
7590 | defined by this specification and for any extension methods for which | ||
7591 | it is not explicitly referred to as part of that method definition. | ||
7592 | |||
7593 | 14.32 Pragma | ||
7594 | |||
7595 | The Pragma general-header field is used to include implementation- | ||
7596 | specific directives that might apply to any recipient along the | ||
7597 | request/response chain. All pragma directives specify optional | ||
7598 | behavior from the viewpoint of the protocol; however, some systems | ||
7599 | MAY require that behavior be consistent with the directives. | ||
7600 | |||
7601 | Pragma = "Pragma" ":" 1#pragma-directive | ||
7602 | pragma-directive = "no-cache" | extension-pragma | ||
7603 | extension-pragma = token [ "=" ( token | quoted-string ) ] | ||
7604 | |||
7605 | When the no-cache directive is present in a request message, an | ||
7606 | application SHOULD forward the request toward the origin server even | ||
7607 | if it has a cached copy of what is being requested. This pragma | ||
7608 | directive has the same semantics as the no-cache cache-directive (see | ||
7609 | section 14.9) and is defined here for backward compatibility with | ||
7610 | HTTP/1.0. Clients SHOULD include both header fields when a no-cache | ||
7611 | request is sent to a server not known to be HTTP/1.1 compliant. | ||
7612 | |||
7613 | |||
7614 | |||
7615 | |||
7616 | |||
7617 | |||
7618 | Fielding, et al. Standards Track [Page 136] | ||
7619 | |||
7620 | RFC 2616 HTTP/1.1 June 1999 | ||
7621 | |||
7622 | |||
7623 | Pragma directives MUST be passed through by a proxy or gateway | ||
7624 | application, regardless of their significance to that application, | ||
7625 | since the directives might be applicable to all recipients along the | ||
7626 | request/response chain. It is not possible to specify a pragma for a | ||
7627 | specific recipient; however, any pragma directive not relevant to a | ||
7628 | recipient SHOULD be ignored by that recipient. | ||
7629 | |||
7630 | HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client had | ||
7631 | sent "Cache-Control: no-cache". No new Pragma directives will be | ||
7632 | defined in HTTP. | ||
7633 | |||
7634 | Note: because the meaning of "Pragma: no-cache as a response | ||
7635 | header field is not actually specified, it does not provide a | ||
7636 | reliable replacement for "Cache-Control: no-cache" in a response | ||
7637 | |||
7638 | 14.33 Proxy-Authenticate | ||
7639 | |||
7640 | The Proxy-Authenticate response-header field MUST be included as part | ||
7641 | of a 407 (Proxy Authentication Required) response. The field value | ||
7642 | consists of a challenge that indicates the authentication scheme and | ||
7643 | parameters applicable to the proxy for this Request-URI. | ||
7644 | |||
7645 | Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge | ||
7646 | |||
7647 | The HTTP access authentication process is described in "HTTP | ||
7648 | Authentication: Basic and Digest Access Authentication" [43]. Unlike | ||
7649 | WWW-Authenticate, the Proxy-Authenticate header field applies only to | ||
7650 | the current connection and SHOULD NOT be passed on to downstream | ||
7651 | clients. However, an intermediate proxy might need to obtain its own | ||
7652 | credentials by requesting them from the downstream client, which in | ||
7653 | some circumstances will appear as if the proxy is forwarding the | ||
7654 | Proxy-Authenticate header field. | ||
7655 | |||
7656 | 14.34 Proxy-Authorization | ||
7657 | |||
7658 | The Proxy-Authorization request-header field allows the client to | ||
7659 | identify itself (or its user) to a proxy which requires | ||
7660 | authentication. The Proxy-Authorization field value consists of | ||
7661 | credentials containing the authentication information of the user | ||
7662 | agent for the proxy and/or realm of the resource being requested. | ||
7663 | |||
7664 | Proxy-Authorization = "Proxy-Authorization" ":" credentials | ||
7665 | |||
7666 | The HTTP access authentication process is described in "HTTP | ||
7667 | Authentication: Basic and Digest Access Authentication" [43] . Unlike | ||
7668 | Authorization, the Proxy-Authorization header field applies only to | ||
7669 | the next outbound proxy that demanded authentication using the Proxy- | ||
7670 | Authenticate field. When multiple proxies are used in a chain, the | ||
7671 | |||
7672 | |||
7673 | |||
7674 | Fielding, et al. Standards Track [Page 137] | ||
7675 | |||
7676 | RFC 2616 HTTP/1.1 June 1999 | ||
7677 | |||
7678 | |||
7679 | Proxy-Authorization header field is consumed by the first outbound | ||
7680 | proxy that was expecting to receive credentials. A proxy MAY relay | ||
7681 | the credentials from the client request to the next proxy if that is | ||
7682 | the mechanism by which the proxies cooperatively authenticate a given | ||
7683 | request. | ||
7684 | |||
7685 | 14.35 Range | ||
7686 | |||
7687 | 14.35.1 Byte Ranges | ||
7688 | |||
7689 | Since all HTTP entities are represented in HTTP messages as sequences | ||
7690 | of bytes, the concept of a byte range is meaningful for any HTTP | ||
7691 | entity. (However, not all clients and servers need to support byte- | ||
7692 | range operations.) | ||
7693 | |||
7694 | Byte range specifications in HTTP apply to the sequence of bytes in | ||
7695 | the entity-body (not necessarily the same as the message-body). | ||
7696 | |||
7697 | A byte range operation MAY specify a single range of bytes, or a set | ||
7698 | of ranges within a single entity. | ||
7699 | |||
7700 | ranges-specifier = byte-ranges-specifier | ||
7701 | byte-ranges-specifier = bytes-unit "=" byte-range-set | ||
7702 | byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) | ||
7703 | byte-range-spec = first-byte-pos "-" [last-byte-pos] | ||
7704 | first-byte-pos = 1*DIGIT | ||
7705 | last-byte-pos = 1*DIGIT | ||
7706 | |||
7707 | The first-byte-pos value in a byte-range-spec gives the byte-offset | ||
7708 | of the first byte in a range. The last-byte-pos value gives the | ||
7709 | byte-offset of the last byte in the range; that is, the byte | ||
7710 | positions specified are inclusive. Byte offsets start at zero. | ||
7711 | |||
7712 | If the last-byte-pos value is present, it MUST be greater than or | ||
7713 | equal to the first-byte-pos in that byte-range-spec, or the byte- | ||
7714 | range-spec is syntactically invalid. The recipient of a byte-range- | ||
7715 | set that includes one or more syntactically invalid byte-range-spec | ||
7716 | values MUST ignore the header field that includes that byte-range- | ||
7717 | set. | ||
7718 | |||
7719 | If the last-byte-pos value is absent, or if the value is greater than | ||
7720 | or equal to the current length of the entity-body, last-byte-pos is | ||
7721 | taken to be equal to one less than the current length of the entity- | ||
7722 | body in bytes. | ||
7723 | |||
7724 | By its choice of last-byte-pos, a client can limit the number of | ||
7725 | bytes retrieved without knowing the size of the entity. | ||
7726 | |||
7727 | |||
7728 | |||
7729 | |||
7730 | Fielding, et al. Standards Track [Page 138] | ||
7731 | |||
7732 | RFC 2616 HTTP/1.1 June 1999 | ||
7733 | |||
7734 | |||
7735 | suffix-byte-range-spec = "-" suffix-length | ||
7736 | suffix-length = 1*DIGIT | ||
7737 | |||
7738 | A suffix-byte-range-spec is used to specify the suffix of the | ||
7739 | entity-body, of a length given by the suffix-length value. (That is, | ||
7740 | this form specifies the last N bytes of an entity-body.) If the | ||
7741 | entity is shorter than the specified suffix-length, the entire | ||
7742 | entity-body is used. | ||
7743 | |||
7744 | If a syntactically valid byte-range-set includes at least one byte- | ||
7745 | range-spec whose first-byte-pos is less than the current length of | ||
7746 | the entity-body, or at least one suffix-byte-range-spec with a non- | ||
7747 | zero suffix-length, then the byte-range-set is satisfiable. | ||
7748 | Otherwise, the byte-range-set is unsatisfiable. If the byte-range-set | ||
7749 | is unsatisfiable, the server SHOULD return a response with a status | ||
7750 | of 416 (Requested range not satisfiable). Otherwise, the server | ||
7751 | SHOULD return a response with a status of 206 (Partial Content) | ||
7752 | containing the satisfiable ranges of the entity-body. | ||
7753 | |||
7754 | Examples of byte-ranges-specifier values (assuming an entity-body of | ||
7755 | length 10000): | ||
7756 | |||
7757 | - The first 500 bytes (byte offsets 0-499, inclusive): bytes=0- | ||
7758 | 499 | ||
7759 | |||
7760 | - The second 500 bytes (byte offsets 500-999, inclusive): | ||
7761 | bytes=500-999 | ||
7762 | |||
7763 | - The final 500 bytes (byte offsets 9500-9999, inclusive): | ||
7764 | bytes=-500 | ||
7765 | |||
7766 | - Or bytes=9500- | ||
7767 | |||
7768 | - The first and last bytes only (bytes 0 and 9999): bytes=0-0,-1 | ||
7769 | |||
7770 | - Several legal but not canonical specifications of the second 500 | ||
7771 | bytes (byte offsets 500-999, inclusive): | ||
7772 | bytes=500-600,601-999 | ||
7773 | bytes=500-700,601-999 | ||
7774 | |||
7775 | 14.35.2 Range Retrieval Requests | ||
7776 | |||
7777 | HTTP retrieval requests using conditional or unconditional GET | ||
7778 | methods MAY request one or more sub-ranges of the entity, instead of | ||
7779 | the entire entity, using the Range request header, which applies to | ||
7780 | the entity returned as the result of the request: | ||
7781 | |||
7782 | Range = "Range" ":" ranges-specifier | ||
7783 | |||
7784 | |||
7785 | |||
7786 | Fielding, et al. Standards Track [Page 139] | ||
7787 | |||
7788 | RFC 2616 HTTP/1.1 June 1999 | ||
7789 | |||
7790 | |||
7791 | A server MAY ignore the Range header. However, HTTP/1.1 origin | ||
7792 | servers and intermediate caches ought to support byte ranges when | ||
7793 | possible, since Range supports efficient recovery from partially | ||
7794 | failed transfers, and supports efficient partial retrieval of large | ||
7795 | entities. | ||
7796 | |||
7797 | If the server supports the Range header and the specified range or | ||
7798 | ranges are appropriate for the entity: | ||
7799 | |||
7800 | - The presence of a Range header in an unconditional GET modifies | ||
7801 | what is returned if the GET is otherwise successful. In other | ||
7802 | words, the response carries a status code of 206 (Partial | ||
7803 | Content) instead of 200 (OK). | ||
7804 | |||
7805 | - The presence of a Range header in a conditional GET (a request | ||
7806 | using one or both of If-Modified-Since and If-None-Match, or | ||
7807 | one or both of If-Unmodified-Since and If-Match) modifies what | ||
7808 | is returned if the GET is otherwise successful and the | ||
7809 | condition is true. It does not affect the 304 (Not Modified) | ||
7810 | response returned if the conditional is false. | ||
7811 | |||
7812 | In some cases, it might be more appropriate to use the If-Range | ||
7813 | header (see section 14.27) in addition to the Range header. | ||
7814 | |||
7815 | If a proxy that supports ranges receives a Range request, forwards | ||
7816 | the request to an inbound server, and receives an entire entity in | ||
7817 | reply, it SHOULD only return the requested range to its client. It | ||
7818 | SHOULD store the entire received response in its cache if that is | ||
7819 | consistent with its cache allocation policies. | ||
7820 | |||
7821 | 14.36 Referer | ||
7822 | |||
7823 | The Referer[sic] request-header field allows the client to specify, | ||
7824 | for the server's benefit, the address (URI) of the resource from | ||
7825 | which the Request-URI was obtained (the "referrer", although the | ||
7826 | header field is misspelled.) The Referer request-header allows a | ||
7827 | server to generate lists of back-links to resources for interest, | ||
7828 | logging, optimized caching, etc. It also allows obsolete or mistyped | ||
7829 | links to be traced for maintenance. The Referer field MUST NOT be | ||
7830 | sent if the Request-URI was obtained from a source that does not have | ||
7831 | its own URI, such as input from the user keyboard. | ||
7832 | |||
7833 | Referer = "Referer" ":" ( absoluteURI | relativeURI ) | ||
7834 | |||
7835 | Example: | ||
7836 | |||
7837 | Referer: http://www.w3.org/hypertext/DataSources/Overview.html | ||
7838 | |||
7839 | |||
7840 | |||
7841 | |||
7842 | Fielding, et al. Standards Track [Page 140] | ||
7843 | |||
7844 | RFC 2616 HTTP/1.1 June 1999 | ||
7845 | |||
7846 | |||
7847 | If the field value is a relative URI, it SHOULD be interpreted | ||
7848 | relative to the Request-URI. The URI MUST NOT include a fragment. See | ||
7849 | section 15.1.3 for security considerations. | ||
7850 | |||
7851 | 14.37 Retry-After | ||
7852 | |||
7853 | The Retry-After response-header field can be used with a 503 (Service | ||
7854 | Unavailable) response to indicate how long the service is expected to | ||
7855 | be unavailable to the requesting client. This field MAY also be used | ||
7856 | with any 3xx (Redirection) response to indicate the minimum time the | ||
7857 | user-agent is asked wait before issuing the redirected request. The | ||
7858 | value of this field can be either an HTTP-date or an integer number | ||
7859 | of seconds (in decimal) after the time of the response. | ||
7860 | |||
7861 | Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds ) | ||
7862 | |||
7863 | Two examples of its use are | ||
7864 | |||
7865 | Retry-After: Fri, 31 Dec 1999 23:59:59 GMT | ||
7866 | Retry-After: 120 | ||
7867 | |||
7868 | In the latter example, the delay is 2 minutes. | ||
7869 | |||
7870 | 14.38 Server | ||
7871 | |||
7872 | The Server response-header field contains information about the | ||
7873 | software used by the origin server to handle the request. The field | ||
7874 | can contain multiple product tokens (section 3.8) and comments | ||
7875 | identifying the server and any significant subproducts. The product | ||
7876 | tokens are listed in order of their significance for identifying the | ||
7877 | application. | ||
7878 | |||
7879 | Server = "Server" ":" 1*( product | comment ) | ||
7880 | |||
7881 | Example: | ||
7882 | |||
7883 | Server: CERN/3.0 libwww/2.17 | ||
7884 | |||
7885 | If the response is being forwarded through a proxy, the proxy | ||
7886 | application MUST NOT modify the Server response-header. Instead, it | ||
7887 | SHOULD include a Via field (as described in section 14.45). | ||
7888 | |||
7889 | Note: Revealing the specific software version of the server might | ||
7890 | allow the server machine to become more vulnerable to attacks | ||
7891 | against software that is known to contain security holes. Server | ||
7892 | implementors are encouraged to make this field a configurable | ||
7893 | option. | ||
7894 | |||
7895 | |||
7896 | |||
7897 | |||
7898 | Fielding, et al. Standards Track [Page 141] | ||
7899 | |||
7900 | RFC 2616 HTTP/1.1 June 1999 | ||
7901 | |||
7902 | |||
7903 | 14.39 TE | ||
7904 | |||
7905 | The TE request-header field indicates what extension transfer-codings | ||
7906 | it is willing to accept in the response and whether or not it is | ||
7907 | willing to accept trailer fields in a chunked transfer-coding. Its | ||
7908 | value may consist of the keyword "trailers" and/or a comma-separated | ||
7909 | list of extension transfer-coding names with optional accept | ||
7910 | parameters (as described in section 3.6). | ||
7911 | |||
7912 | TE = "TE" ":" #( t-codings ) | ||
7913 | t-codings = "trailers" | ( transfer-extension [ accept-params ] ) | ||
7914 | |||
7915 | The presence of the keyword "trailers" indicates that the client is | ||
7916 | willing to accept trailer fields in a chunked transfer-coding, as | ||
7917 | defined in section 3.6.1. This keyword is reserved for use with | ||
7918 | transfer-coding values even though it does not itself represent a | ||
7919 | transfer-coding. | ||
7920 | |||
7921 | Examples of its use are: | ||
7922 | |||
7923 | TE: deflate | ||
7924 | TE: | ||
7925 | TE: trailers, deflate;q=0.5 | ||
7926 | |||
7927 | The TE header field only applies to the immediate connection. | ||
7928 | Therefore, the keyword MUST be supplied within a Connection header | ||
7929 | field (section 14.10) whenever TE is present in an HTTP/1.1 message. | ||
7930 | |||
7931 | A server tests whether a transfer-coding is acceptable, according to | ||
7932 | a TE field, using these rules: | ||
7933 | |||
7934 | 1. The "chunked" transfer-coding is always acceptable. If the | ||
7935 | keyword "trailers" is listed, the client indicates that it is | ||
7936 | willing to accept trailer fields in the chunked response on | ||
7937 | behalf of itself and any downstream clients. The implication is | ||
7938 | that, if given, the client is stating that either all | ||
7939 | downstream clients are willing to accept trailer fields in the | ||
7940 | forwarded response, or that it will attempt to buffer the | ||
7941 | response on behalf of downstream recipients. | ||
7942 | |||
7943 | Note: HTTP/1.1 does not define any means to limit the size of a | ||
7944 | chunked response such that a client can be assured of buffering | ||
7945 | the entire response. | ||
7946 | |||
7947 | 2. If the transfer-coding being tested is one of the transfer- | ||
7948 | codings listed in the TE field, then it is acceptable unless it | ||
7949 | is accompanied by a qvalue of 0. (As defined in section 3.9, a | ||
7950 | qvalue of 0 means "not acceptable.") | ||
7951 | |||
7952 | |||
7953 | |||
7954 | Fielding, et al. Standards Track [Page 142] | ||
7955 | |||
7956 | RFC 2616 HTTP/1.1 June 1999 | ||
7957 | |||
7958 | |||
7959 | 3. If multiple transfer-codings are acceptable, then the | ||
7960 | acceptable transfer-coding with the highest non-zero qvalue is | ||
7961 | preferred. The "chunked" transfer-coding always has a qvalue | ||
7962 | of 1. | ||
7963 | |||
7964 | If the TE field-value is empty or if no TE field is present, the only | ||
7965 | transfer-coding is "chunked". A message with no transfer-coding is | ||
7966 | always acceptable. | ||
7967 | |||
7968 | 14.40 Trailer | ||
7969 | |||
7970 | The Trailer general field value indicates that the given set of | ||
7971 | header fields is present in the trailer of a message encoded with | ||
7972 | chunked transfer-coding. | ||
7973 | |||
7974 | Trailer = "Trailer" ":" 1#field-name | ||
7975 | |||
7976 | An HTTP/1.1 message SHOULD include a Trailer header field in a | ||
7977 | message using chunked transfer-coding with a non-empty trailer. Doing | ||
7978 | so allows the recipient to know which header fields to expect in the | ||
7979 | trailer. | ||
7980 | |||
7981 | If no Trailer header field is present, the trailer SHOULD NOT include | ||
7982 | any header fields. See section 3.6.1 for restrictions on the use of | ||
7983 | trailer fields in a "chunked" transfer-coding. | ||
7984 | |||
7985 | Message header fields listed in the Trailer header field MUST NOT | ||
7986 | include the following header fields: | ||
7987 | |||
7988 | . Transfer-Encoding | ||
7989 | |||
7990 | . Content-Length | ||
7991 | |||
7992 | . Trailer | ||
7993 | |||
7994 | 14.41 Transfer-Encoding | ||
7995 | |||
7996 | The Transfer-Encoding general-header field indicates what (if any) | ||
7997 | type of transformation has been applied to the message body in order | ||
7998 | to safely transfer it between the sender and the recipient. This | ||
7999 | differs from the content-coding in that the transfer-coding is a | ||
8000 | property of the message, not of the entity. | ||
8001 | |||
8002 | Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding | ||
8003 | |||
8004 | Transfer-codings are defined in section 3.6. An example is: | ||
8005 | |||
8006 | Transfer-Encoding: chunked | ||
8007 | |||
8008 | |||
8009 | |||
8010 | Fielding, et al. Standards Track [Page 143] | ||
8011 | |||
8012 | RFC 2616 HTTP/1.1 June 1999 | ||
8013 | |||
8014 | |||
8015 | If multiple encodings have been applied to an entity, the transfer- | ||
8016 | codings MUST be listed in the order in which they were applied. | ||
8017 | Additional information about the encoding parameters MAY be provided | ||
8018 | by other entity-header fields not defined by this specification. | ||
8019 | |||
8020 | Many older HTTP/1.0 applications do not understand the Transfer- | ||
8021 | Encoding header. | ||
8022 | |||
8023 | 14.42 Upgrade | ||
8024 | |||
8025 | The Upgrade general-header allows the client to specify what | ||
8026 | additional communication protocols it supports and would like to use | ||
8027 | if the server finds it appropriate to switch protocols. The server | ||
8028 | MUST use the Upgrade header field within a 101 (Switching Protocols) | ||
8029 | response to indicate which protocol(s) are being switched. | ||
8030 | |||
8031 | Upgrade = "Upgrade" ":" 1#product | ||
8032 | |||
8033 | For example, | ||
8034 | |||
8035 | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 | ||
8036 | |||
8037 | The Upgrade header field is intended to provide a simple mechanism | ||
8038 | for transition from HTTP/1.1 to some other, incompatible protocol. It | ||
8039 | does so by allowing the client to advertise its desire to use another | ||
8040 | protocol, such as a later version of HTTP with a higher major version | ||
8041 | number, even though the current request has been made using HTTP/1.1. | ||
8042 | This eases the difficult transition between incompatible protocols by | ||
8043 | allowing the client to initiate a request in the more commonly | ||
8044 | supported protocol while indicating to the server that it would like | ||
8045 | to use a "better" protocol if available (where "better" is determined | ||
8046 | by the server, possibly according to the nature of the method and/or | ||
8047 | resource being requested). | ||
8048 | |||
8049 | The Upgrade header field only applies to switching application-layer | ||
8050 | protocols upon the existing transport-layer connection. Upgrade | ||
8051 | cannot be used to insist on a protocol change; its acceptance and use | ||
8052 | by the server is optional. The capabilities and nature of the | ||
8053 | application-layer communication after the protocol change is entirely | ||
8054 | dependent upon the new protocol chosen, although the first action | ||
8055 | after changing the protocol MUST be a response to the initial HTTP | ||
8056 | request containing the Upgrade header field. | ||
8057 | |||
8058 | The Upgrade header field only applies to the immediate connection. | ||
8059 | Therefore, the upgrade keyword MUST be supplied within a Connection | ||
8060 | header field (section 14.10) whenever Upgrade is present in an | ||
8061 | HTTP/1.1 message. | ||
8062 | |||
8063 | |||
8064 | |||
8065 | |||
8066 | Fielding, et al. Standards Track [Page 144] | ||
8067 | |||
8068 | RFC 2616 HTTP/1.1 June 1999 | ||
8069 | |||
8070 | |||
8071 | The Upgrade header field cannot be used to indicate a switch to a | ||
8072 | protocol on a different connection. For that purpose, it is more | ||
8073 | appropriate to use a 301, 302, 303, or 305 redirection response. | ||
8074 | |||
8075 | This specification only defines the protocol name "HTTP" for use by | ||
8076 | the family of Hypertext Transfer Protocols, as defined by the HTTP | ||
8077 | version rules of section 3.1 and future updates to this | ||
8078 | specification. Any token can be used as a protocol name; however, it | ||
8079 | will only be useful if both the client and server associate the name | ||
8080 | with the same protocol. | ||
8081 | |||
8082 | 14.43 User-Agent | ||
8083 | |||
8084 | The User-Agent request-header field contains information about the | ||
8085 | user agent originating the request. This is for statistical purposes, | ||
8086 | the tracing of protocol violations, and automated recognition of user | ||
8087 | agents for the sake of tailoring responses to avoid particular user | ||
8088 | agent limitations. User agents SHOULD include this field with | ||
8089 | requests. The field can contain multiple product tokens (section 3.8) | ||
8090 | and comments identifying the agent and any subproducts which form a | ||
8091 | significant part of the user agent. By convention, the product tokens | ||
8092 | are listed in order of their significance for identifying the | ||
8093 | application. | ||
8094 | |||
8095 | User-Agent = "User-Agent" ":" 1*( product | comment ) | ||
8096 | |||
8097 | Example: | ||
8098 | |||
8099 | User-Agent: CERN-LineMode/2.15 libwww/2.17b3 | ||
8100 | |||
8101 | 14.44 Vary | ||
8102 | |||
8103 | The Vary field value indicates the set of request-header fields that | ||
8104 | fully determines, while the response is fresh, whether a cache is | ||
8105 | permitted to use the response to reply to a subsequent request | ||
8106 | without revalidation. For uncacheable or stale responses, the Vary | ||
8107 | field value advises the user agent about the criteria that were used | ||
8108 | to select the representation. A Vary field value of "*" implies that | ||
8109 | a cache cannot determine from the request headers of a subsequent | ||
8110 | request whether this response is the appropriate representation. See | ||
8111 | section 13.6 for use of the Vary header field by caches. | ||
8112 | |||
8113 | Vary = "Vary" ":" ( "*" | 1#field-name ) | ||
8114 | |||
8115 | An HTTP/1.1 server SHOULD include a Vary header field with any | ||
8116 | cacheable response that is subject to server-driven negotiation. | ||
8117 | Doing so allows a cache to properly interpret future requests on that | ||
8118 | resource and informs the user agent about the presence of negotiation | ||
8119 | |||
8120 | |||
8121 | |||
8122 | Fielding, et al. Standards Track [Page 145] | ||
8123 | |||
8124 | RFC 2616 HTTP/1.1 June 1999 | ||
8125 | |||
8126 | |||
8127 | on that resource. A server MAY include a Vary header field with a | ||
8128 | non-cacheable response that is subject to server-driven negotiation, | ||
8129 | since this might provide the user agent with useful information about | ||
8130 | the dimensions over which the response varies at the time of the | ||
8131 | response. | ||
8132 | |||
8133 | A Vary field value consisting of a list of field-names signals that | ||
8134 | the representation selected for the response is based on a selection | ||
8135 | algorithm which considers ONLY the listed request-header field values | ||
8136 | in selecting the most appropriate representation. A cache MAY assume | ||
8137 | that the same selection will be made for future requests with the | ||
8138 | same values for the listed field names, for the duration of time for | ||
8139 | which the response is fresh. | ||
8140 | |||
8141 | The field-names given are not limited to the set of standard | ||
8142 | request-header fields defined by this specification. Field names are | ||
8143 | case-insensitive. | ||
8144 | |||
8145 | A Vary field value of "*" signals that unspecified parameters not | ||
8146 | limited to the request-headers (e.g., the network address of the | ||
8147 | client), play a role in the selection of the response representation. | ||
8148 | The "*" value MUST NOT be generated by a proxy server; it may only be | ||
8149 | generated by an origin server. | ||
8150 | |||
8151 | 14.45 Via | ||
8152 | |||
8153 | The Via general-header field MUST be used by gateways and proxies to | ||
8154 | indicate the intermediate protocols and recipients between the user | ||
8155 | agent and the server on requests, and between the origin server and | ||
8156 | the client on responses. It is analogous to the "Received" field of | ||
8157 | RFC 822 [9] and is intended to be used for tracking message forwards, | ||
8158 | avoiding request loops, and identifying the protocol capabilities of | ||
8159 | all senders along the request/response chain. | ||
8160 | |||
8161 | Via = "Via" ":" 1#( received-protocol received-by [ comment ] ) | ||
8162 | received-protocol = [ protocol-name "/" ] protocol-version | ||
8163 | protocol-name = token | ||
8164 | protocol-version = token | ||
8165 | received-by = ( host [ ":" port ] ) | pseudonym | ||
8166 | pseudonym = token | ||
8167 | |||
8168 | The received-protocol indicates the protocol version of the message | ||
8169 | received by the server or client along each segment of the | ||
8170 | request/response chain. The received-protocol version is appended to | ||
8171 | the Via field value when the message is forwarded so that information | ||
8172 | about the protocol capabilities of upstream applications remains | ||
8173 | visible to all recipients. | ||
8174 | |||
8175 | |||
8176 | |||
8177 | |||
8178 | Fielding, et al. Standards Track [Page 146] | ||
8179 | |||
8180 | RFC 2616 HTTP/1.1 June 1999 | ||
8181 | |||
8182 | |||
8183 | The protocol-name is optional if and only if it would be "HTTP". The | ||
8184 | received-by field is normally the host and optional port number of a | ||
8185 | recipient server or client that subsequently forwarded the message. | ||
8186 | However, if the real host is considered to be sensitive information, | ||
8187 | it MAY be replaced by a pseudonym. If the port is not given, it MAY | ||
8188 | be assumed to be the default port of the received-protocol. | ||
8189 | |||
8190 | Multiple Via field values represents each proxy or gateway that has | ||
8191 | forwarded the message. Each recipient MUST append its information | ||
8192 | such that the end result is ordered according to the sequence of | ||
8193 | forwarding applications. | ||
8194 | |||
8195 | Comments MAY be used in the Via header field to identify the software | ||
8196 | of the recipient proxy or gateway, analogous to the User-Agent and | ||
8197 | Server header fields. However, all comments in the Via field are | ||
8198 | optional and MAY be removed by any recipient prior to forwarding the | ||
8199 | message. | ||
8200 | |||
8201 | For example, a request message could be sent from an HTTP/1.0 user | ||
8202 | agent to an internal proxy code-named "fred", which uses HTTP/1.1 to | ||
8203 | forward the request to a public proxy at nowhere.com, which completes | ||
8204 | the request by forwarding it to the origin server at www.ics.uci.edu. | ||
8205 | The request received by www.ics.uci.edu would then have the following | ||
8206 | Via header field: | ||
8207 | |||
8208 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) | ||
8209 | |||
8210 | Proxies and gateways used as a portal through a network firewall | ||
8211 | SHOULD NOT, by default, forward the names and ports of hosts within | ||
8212 | the firewall region. This information SHOULD only be propagated if | ||
8213 | explicitly enabled. If not enabled, the received-by host of any host | ||
8214 | behind the firewall SHOULD be replaced by an appropriate pseudonym | ||
8215 | for that host. | ||
8216 | |||
8217 | For organizations that have strong privacy requirements for hiding | ||
8218 | internal structures, a proxy MAY combine an ordered subsequence of | ||
8219 | Via header field entries with identical received-protocol values into | ||
8220 | a single such entry. For example, | ||
8221 | |||
8222 | Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy | ||
8223 | |||
8224 | could be collapsed to | ||
8225 | |||
8226 | Via: 1.0 ricky, 1.1 mertz, 1.0 lucy | ||
8227 | |||
8228 | |||
8229 | |||
8230 | |||
8231 | |||
8232 | |||
8233 | |||
8234 | Fielding, et al. Standards Track [Page 147] | ||
8235 | |||
8236 | RFC 2616 HTTP/1.1 June 1999 | ||
8237 | |||
8238 | |||
8239 | Applications SHOULD NOT combine multiple entries unless they are all | ||
8240 | under the same organizational control and the hosts have already been | ||
8241 | replaced by pseudonyms. Applications MUST NOT combine entries which | ||
8242 | have different received-protocol values. | ||
8243 | |||
8244 | 14.46 Warning | ||
8245 | |||
8246 | The Warning general-header field is used to carry additional | ||
8247 | information about the status or transformation of a message which | ||
8248 | might not be reflected in the message. This information is typically | ||
8249 | used to warn about a possible lack of semantic transparency from | ||
8250 | caching operations or transformations applied to the entity body of | ||
8251 | the message. | ||
8252 | |||
8253 | Warning headers are sent with responses using: | ||
8254 | |||
8255 | Warning = "Warning" ":" 1#warning-value | ||
8256 | |||
8257 | warning-value = warn-code SP warn-agent SP warn-text | ||
8258 | [SP warn-date] | ||
8259 | |||
8260 | warn-code = 3DIGIT | ||
8261 | warn-agent = ( host [ ":" port ] ) | pseudonym | ||
8262 | ; the name or pseudonym of the server adding | ||
8263 | ; the Warning header, for use in debugging | ||
8264 | warn-text = quoted-string | ||
8265 | warn-date = <"> HTTP-date <"> | ||
8266 | |||
8267 | A response MAY carry more than one Warning header. | ||
8268 | |||
8269 | The warn-text SHOULD be in a natural language and character set that | ||
8270 | is most likely to be intelligible to the human user receiving the | ||
8271 | response. This decision MAY be based on any available knowledge, such | ||
8272 | as the location of the cache or user, the Accept-Language field in a | ||
8273 | request, the Content-Language field in a response, etc. The default | ||
8274 | language is English and the default character set is ISO-8859-1. | ||
8275 | |||
8276 | If a character set other than ISO-8859-1 is used, it MUST be encoded | ||
8277 | in the warn-text using the method described in RFC 2047 [14]. | ||
8278 | |||
8279 | Warning headers can in general be applied to any message, however | ||
8280 | some specific warn-codes are specific to caches and can only be | ||
8281 | applied to response messages. New Warning headers SHOULD be added | ||
8282 | after any existing Warning headers. A cache MUST NOT delete any | ||
8283 | Warning header that it received with a message. However, if a cache | ||
8284 | successfully validates a cache entry, it SHOULD remove any Warning | ||
8285 | headers previously attached to that entry except as specified for | ||
8286 | |||
8287 | |||
8288 | |||
8289 | |||
8290 | Fielding, et al. Standards Track [Page 148] | ||
8291 | |||
8292 | RFC 2616 HTTP/1.1 June 1999 | ||
8293 | |||
8294 | |||
8295 | specific Warning codes. It MUST then add any Warning headers received | ||
8296 | in the validating response. In other words, Warning headers are those | ||
8297 | that would be attached to the most recent relevant response. | ||
8298 | |||
8299 | When multiple Warning headers are attached to a response, the user | ||
8300 | agent ought to inform the user of as many of them as possible, in the | ||
8301 | order that they appear in the response. If it is not possible to | ||
8302 | inform the user of all of the warnings, the user agent SHOULD follow | ||
8303 | these heuristics: | ||
8304 | |||
8305 | - Warnings that appear early in the response take priority over | ||
8306 | those appearing later in the response. | ||
8307 | |||
8308 | - Warnings in the user's preferred character set take priority | ||
8309 | over warnings in other character sets but with identical warn- | ||
8310 | codes and warn-agents. | ||
8311 | |||
8312 | Systems that generate multiple Warning headers SHOULD order them with | ||
8313 | this user agent behavior in mind. | ||
8314 | |||
8315 | Requirements for the behavior of caches with respect to Warnings are | ||
8316 | stated in section 13.1.2. | ||
8317 | |||
8318 | This is a list of the currently-defined warn-codes, each with a | ||
8319 | recommended warn-text in English, and a description of its meaning. | ||
8320 | |||
8321 | 110 Response is stale | ||
8322 | MUST be included whenever the returned response is stale. | ||
8323 | |||
8324 | 111 Revalidation failed | ||
8325 | MUST be included if a cache returns a stale response because an | ||
8326 | attempt to revalidate the response failed, due to an inability to | ||
8327 | reach the server. | ||
8328 | |||
8329 | 112 Disconnected operation | ||
8330 | SHOULD be included if the cache is intentionally disconnected from | ||
8331 | the rest of the network for a period of time. | ||
8332 | |||
8333 | 113 Heuristic expiration | ||
8334 | MUST be included if the cache heuristically chose a freshness | ||
8335 | lifetime greater than 24 hours and the response's age is greater | ||
8336 | than 24 hours. | ||
8337 | |||
8338 | 199 Miscellaneous warning | ||
8339 | The warning text MAY include arbitrary information to be presented | ||
8340 | to a human user, or logged. A system receiving this warning MUST | ||
8341 | NOT take any automated action, besides presenting the warning to | ||
8342 | the user. | ||
8343 | |||
8344 | |||
8345 | |||
8346 | Fielding, et al. Standards Track [Page 149] | ||
8347 | |||
8348 | RFC 2616 HTTP/1.1 June 1999 | ||
8349 | |||
8350 | |||
8351 | 214 Transformation applied | ||
8352 | MUST be added by an intermediate cache or proxy if it applies any | ||
8353 | transformation changing the content-coding (as specified in the | ||
8354 | Content-Encoding header) or media-type (as specified in the | ||
8355 | Content-Type header) of the response, or the entity-body of the | ||
8356 | response, unless this Warning code already appears in the response. | ||
8357 | |||
8358 | 299 Miscellaneous persistent warning | ||
8359 | The warning text MAY include arbitrary information to be presented | ||
8360 | to a human user, or logged. A system receiving this warning MUST | ||
8361 | NOT take any automated action. | ||
8362 | |||
8363 | If an implementation sends a message with one or more Warning headers | ||
8364 | whose version is HTTP/1.0 or lower, then the sender MUST include in | ||
8365 | each warning-value a warn-date that matches the date in the response. | ||
8366 | |||
8367 | If an implementation receives a message with a warning-value that | ||
8368 | includes a warn-date, and that warn-date is different from the Date | ||
8369 | value in the response, then that warning-value MUST be deleted from | ||
8370 | the message before storing, forwarding, or using it. (This prevents | ||
8371 | bad consequences of naive caching of Warning header fields.) If all | ||
8372 | of the warning-values are deleted for this reason, the Warning header | ||
8373 | MUST be deleted as well. | ||
8374 | |||
8375 | 14.47 WWW-Authenticate | ||
8376 | |||
8377 | The WWW-Authenticate response-header field MUST be included in 401 | ||
8378 | (Unauthorized) response messages. The field value consists of at | ||
8379 | least one challenge that indicates the authentication scheme(s) and | ||
8380 | parameters applicable to the Request-URI. | ||
8381 | |||
8382 | WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge | ||
8383 | |||
8384 | The HTTP access authentication process is described in "HTTP | ||
8385 | Authentication: Basic and Digest Access Authentication" [43]. User | ||
8386 | agents are advised to take special care in parsing the WWW- | ||
8387 | Authenticate field value as it might contain more than one challenge, | ||
8388 | or if more than one WWW-Authenticate header field is provided, the | ||
8389 | contents of a challenge itself can contain a comma-separated list of | ||
8390 | authentication parameters. | ||
8391 | |||
8392 | 15 Security Considerations | ||
8393 | |||
8394 | This section is meant to inform application developers, information | ||
8395 | providers, and users of the security limitations in HTTP/1.1 as | ||
8396 | described by this document. The discussion does not include | ||
8397 | definitive solutions to the problems revealed, though it does make | ||
8398 | some suggestions for reducing security risks. | ||
8399 | |||
8400 | |||
8401 | |||
8402 | Fielding, et al. Standards Track [Page 150] | ||
8403 | |||
8404 | RFC 2616 HTTP/1.1 June 1999 | ||
8405 | |||
8406 | |||
8407 | 15.1 Personal Information | ||
8408 | |||
8409 | HTTP clients are often privy to large amounts of personal information | ||
8410 | (e.g. the user's name, location, mail address, passwords, encryption | ||
8411 | keys, etc.), and SHOULD be very careful to prevent unintentional | ||
8412 | leakage of this information via the HTTP protocol to other sources. | ||
8413 | We very strongly recommend that a convenient interface be provided | ||
8414 | for the user to control dissemination of such information, and that | ||
8415 | designers and implementors be particularly careful in this area. | ||
8416 | History shows that errors in this area often create serious security | ||
8417 | and/or privacy problems and generate highly adverse publicity for the | ||
8418 | implementor's company. | ||
8419 | |||
8420 | 15.1.1 Abuse of Server Log Information | ||
8421 | |||
8422 | A server is in the position to save personal data about a user's | ||
8423 | requests which might identify their reading patterns or subjects of | ||
8424 | interest. This information is clearly confidential in nature and its | ||
8425 | handling can be constrained by law in certain countries. People using | ||
8426 | the HTTP protocol to provide data are responsible for ensuring that | ||
8427 | such material is not distributed without the permission of any | ||
8428 | individuals that are identifiable by the published results. | ||
8429 | |||
8430 | 15.1.2 Transfer of Sensitive Information | ||
8431 | |||
8432 | Like any generic data transfer protocol, HTTP cannot regulate the | ||
8433 | content of the data that is transferred, nor is there any a priori | ||
8434 | method of determining the sensitivity of any particular piece of | ||
8435 | information within the context of any given request. Therefore, | ||
8436 | applications SHOULD supply as much control over this information as | ||
8437 | possible to the provider of that information. Four header fields are | ||
8438 | worth special mention in this context: Server, Via, Referer and From. | ||
8439 | |||
8440 | Revealing the specific software version of the server might allow the | ||
8441 | server machine to become more vulnerable to attacks against software | ||
8442 | that is known to contain security holes. Implementors SHOULD make the | ||
8443 | Server header field a configurable option. | ||
8444 | |||
8445 | Proxies which serve as a portal through a network firewall SHOULD | ||
8446 | take special precautions regarding the transfer of header information | ||
8447 | that identifies the hosts behind the firewall. In particular, they | ||
8448 | SHOULD remove, or replace with sanitized versions, any Via fields | ||
8449 | generated behind the firewall. | ||
8450 | |||
8451 | The Referer header allows reading patterns to be studied and reverse | ||
8452 | links drawn. Although it can be very useful, its power can be abused | ||
8453 | if user details are not separated from the information contained in | ||
8454 | |||
8455 | |||
8456 | |||
8457 | |||
8458 | Fielding, et al. Standards Track [Page 151] | ||
8459 | |||
8460 | RFC 2616 HTTP/1.1 June 1999 | ||
8461 | |||
8462 | |||
8463 | the Referer. Even when the personal information has been removed, the | ||
8464 | Referer header might indicate a private document's URI whose | ||
8465 | publication would be inappropriate. | ||
8466 | |||
8467 | The information sent in the From field might conflict with the user's | ||
8468 | privacy interests or their site's security policy, and hence it | ||
8469 | SHOULD NOT be transmitted without the user being able to disable, | ||
8470 | enable, and modify the contents of the field. The user MUST be able | ||
8471 | to set the contents of this field within a user preference or | ||
8472 | application defaults configuration. | ||
8473 | |||
8474 | We suggest, though do not require, that a convenient toggle interface | ||
8475 | be provided for the user to enable or disable the sending of From and | ||
8476 | Referer information. | ||
8477 | |||
8478 | The User-Agent (section 14.43) or Server (section 14.38) header | ||
8479 | fields can sometimes be used to determine that a specific client or | ||
8480 | server have a particular security hole which might be exploited. | ||
8481 | Unfortunately, this same information is often used for other valuable | ||
8482 | purposes for which HTTP currently has no better mechanism. | ||
8483 | |||
8484 | 15.1.3 Encoding Sensitive Information in URI's | ||
8485 | |||
8486 | Because the source of a link might be private information or might | ||
8487 | reveal an otherwise private information source, it is strongly | ||
8488 | recommended that the user be able to select whether or not the | ||
8489 | Referer field is sent. For example, a browser client could have a | ||
8490 | toggle switch for browsing openly/anonymously, which would | ||
8491 | respectively enable/disable the sending of Referer and From | ||
8492 | information. | ||
8493 | |||
8494 | Clients SHOULD NOT include a Referer header field in a (non-secure) | ||
8495 | HTTP request if the referring page was transferred with a secure | ||
8496 | protocol. | ||
8497 | |||
8498 | Authors of services which use the HTTP protocol SHOULD NOT use GET | ||
8499 | based forms for the submission of sensitive data, because this will | ||
8500 | cause this data to be encoded in the Request-URI. Many existing | ||
8501 | servers, proxies, and user agents will log the request URI in some | ||
8502 | place where it might be visible to third parties. Servers can use | ||
8503 | POST-based form submission instead | ||
8504 | |||
8505 | 15.1.4 Privacy Issues Connected to Accept Headers | ||
8506 | |||
8507 | Accept request-headers can reveal information about the user to all | ||
8508 | servers which are accessed. The Accept-Language header in particular | ||
8509 | can reveal information the user would consider to be of a private | ||
8510 | nature, because the understanding of particular languages is often | ||
8511 | |||
8512 | |||
8513 | |||
8514 | Fielding, et al. Standards Track [Page 152] | ||
8515 | |||
8516 | RFC 2616 HTTP/1.1 June 1999 | ||
8517 | |||
8518 | |||
8519 | strongly correlated to the membership of a particular ethnic group. | ||
8520 | User agents which offer the option to configure the contents of an | ||
8521 | Accept-Language header to be sent in every request are strongly | ||
8522 | encouraged to let the configuration process include a message which | ||
8523 | makes the user aware of the loss of privacy involved. | ||
8524 | |||
8525 | An approach that limits the loss of privacy would be for a user agent | ||
8526 | to omit the sending of Accept-Language headers by default, and to ask | ||
8527 | the user whether or not to start sending Accept-Language headers to a | ||
8528 | server if it detects, by looking for any Vary response-header fields | ||
8529 | generated by the server, that such sending could improve the quality | ||
8530 | of service. | ||
8531 | |||
8532 | Elaborate user-customized accept header fields sent in every request, | ||
8533 | in particular if these include quality values, can be used by servers | ||
8534 | as relatively reliable and long-lived user identifiers. Such user | ||
8535 | identifiers would allow content providers to do click-trail tracking, | ||
8536 | and would allow collaborating content providers to match cross-server | ||
8537 | click-trails or form submissions of individual users. Note that for | ||
8538 | many users not behind a proxy, the network address of the host | ||
8539 | running the user agent will also serve as a long-lived user | ||
8540 | identifier. In environments where proxies are used to enhance | ||
8541 | privacy, user agents ought to be conservative in offering accept | ||
8542 | header configuration options to end users. As an extreme privacy | ||
8543 | measure, proxies could filter the accept headers in relayed requests. | ||
8544 | General purpose user agents which provide a high degree of header | ||
8545 | configurability SHOULD warn users about the loss of privacy which can | ||
8546 | be involved. | ||
8547 | |||
8548 | 15.2 Attacks Based On File and Path Names | ||
8549 | |||
8550 | Implementations of HTTP origin servers SHOULD be careful to restrict | ||
8551 | the documents returned by HTTP requests to be only those that were | ||
8552 | intended by the server administrators. If an HTTP server translates | ||
8553 | HTTP URIs directly into file system calls, the server MUST take | ||
8554 | special care not to serve files that were not intended to be | ||
8555 | delivered to HTTP clients. For example, UNIX, Microsoft Windows, and | ||
8556 | other operating systems use ".." as a path component to indicate a | ||
8557 | directory level above the current one. On such a system, an HTTP | ||
8558 | server MUST disallow any such construct in the Request-URI if it | ||
8559 | would otherwise allow access to a resource outside those intended to | ||
8560 | be accessible via the HTTP server. Similarly, files intended for | ||
8561 | reference only internally to the server (such as access control | ||
8562 | files, configuration files, and script code) MUST be protected from | ||
8563 | inappropriate retrieval, since they might contain sensitive | ||
8564 | information. Experience has shown that minor bugs in such HTTP server | ||
8565 | implementations have turned into security risks. | ||
8566 | |||
8567 | |||
8568 | |||
8569 | |||
8570 | Fielding, et al. Standards Track [Page 153] | ||
8571 | |||
8572 | RFC 2616 HTTP/1.1 June 1999 | ||
8573 | |||
8574 | |||
8575 | 15.3 DNS Spoofing | ||
8576 | |||
8577 | Clients using HTTP rely heavily on the Domain Name Service, and are | ||
8578 | thus generally prone to security attacks based on the deliberate | ||
8579 | mis-association of IP addresses and DNS names. Clients need to be | ||
8580 | cautious in assuming the continuing validity of an IP number/DNS name | ||
8581 | association. | ||
8582 | |||
8583 | In particular, HTTP clients SHOULD rely on their name resolver for | ||
8584 | confirmation of an IP number/DNS name association, rather than | ||
8585 | caching the result of previous host name lookups. Many platforms | ||
8586 | already can cache host name lookups locally when appropriate, and | ||
8587 | they SHOULD be configured to do so. It is proper for these lookups to | ||
8588 | be cached, however, only when the TTL (Time To Live) information | ||
8589 | reported by the name server makes it likely that the cached | ||
8590 | information will remain useful. | ||
8591 | |||
8592 | If HTTP clients cache the results of host name lookups in order to | ||
8593 | achieve a performance improvement, they MUST observe the TTL | ||
8594 | information reported by DNS. | ||
8595 | |||
8596 | If HTTP clients do not observe this rule, they could be spoofed when | ||
8597 | a previously-accessed server's IP address changes. As network | ||
8598 | renumbering is expected to become increasingly common [24], the | ||
8599 | possibility of this form of attack will grow. Observing this | ||
8600 | requirement thus reduces this potential security vulnerability. | ||
8601 | |||
8602 | This requirement also improves the load-balancing behavior of clients | ||
8603 | for replicated servers using the same DNS name and reduces the | ||
8604 | likelihood of a user's experiencing failure in accessing sites which | ||
8605 | use that strategy. | ||
8606 | |||
8607 | 15.4 Location Headers and Spoofing | ||
8608 | |||
8609 | If a single server supports multiple organizations that do not trust | ||
8610 | one another, then it MUST check the values of Location and Content- | ||
8611 | Location headers in responses that are generated under control of | ||
8612 | said organizations to make sure that they do not attempt to | ||
8613 | invalidate resources over which they have no authority. | ||
8614 | |||
8615 | 15.5 Content-Disposition Issues | ||
8616 | |||
8617 | RFC 1806 [35], from which the often implemented Content-Disposition | ||
8618 | (see section 19.5.1) header in HTTP is derived, has a number of very | ||
8619 | serious security considerations. Content-Disposition is not part of | ||
8620 | the HTTP standard, but since it is widely implemented, we are | ||
8621 | documenting its use and risks for implementors. See RFC 2183 [49] | ||
8622 | (which updates RFC 1806) for details. | ||
8623 | |||
8624 | |||
8625 | |||
8626 | Fielding, et al. Standards Track [Page 154] | ||
8627 | |||
8628 | RFC 2616 HTTP/1.1 June 1999 | ||
8629 | |||
8630 | |||
8631 | 15.6 Authentication Credentials and Idle Clients | ||
8632 | |||
8633 | Existing HTTP clients and user agents typically retain authentication | ||
8634 | information indefinitely. HTTP/1.1. does not provide a method for a | ||
8635 | server to direct clients to discard these cached credentials. This is | ||
8636 | a significant defect that requires further extensions to HTTP. | ||
8637 | Circumstances under which credential caching can interfere with the | ||
8638 | application's security model include but are not limited to: | ||
8639 | |||
8640 | - Clients which have been idle for an extended period following | ||
8641 | which the server might wish to cause the client to reprompt the | ||
8642 | user for credentials. | ||
8643 | |||
8644 | - Applications which include a session termination indication | ||
8645 | (such as a `logout' or `commit' button on a page) after which | ||
8646 | the server side of the application `knows' that there is no | ||
8647 | further reason for the client to retain the credentials. | ||
8648 | |||
8649 | This is currently under separate study. There are a number of work- | ||
8650 | arounds to parts of this problem, and we encourage the use of | ||
8651 | password protection in screen savers, idle time-outs, and other | ||
8652 | methods which mitigate the security problems inherent in this | ||
8653 | problem. In particular, user agents which cache credentials are | ||
8654 | encouraged to provide a readily accessible mechanism for discarding | ||
8655 | cached credentials under user control. | ||
8656 | |||
8657 | 15.7 Proxies and Caching | ||
8658 | |||
8659 | By their very nature, HTTP proxies are men-in-the-middle, and | ||
8660 | represent an opportunity for man-in-the-middle attacks. Compromise of | ||
8661 | the systems on which the proxies run can result in serious security | ||
8662 | and privacy problems. Proxies have access to security-related | ||
8663 | information, personal information about individual users and | ||
8664 | organizations, and proprietary information belonging to users and | ||
8665 | content providers. A compromised proxy, or a proxy implemented or | ||
8666 | configured without regard to security and privacy considerations, | ||
8667 | might be used in the commission of a wide range of potential attacks. | ||
8668 | |||
8669 | Proxy operators should protect the systems on which proxies run as | ||
8670 | they would protect any system that contains or transports sensitive | ||
8671 | information. In particular, log information gathered at proxies often | ||
8672 | contains highly sensitive personal information, and/or information | ||
8673 | about organizations. Log information should be carefully guarded, and | ||
8674 | appropriate guidelines for use developed and followed. (Section | ||
8675 | 15.1.1). | ||
8676 | |||
8677 | |||
8678 | |||
8679 | |||
8680 | |||
8681 | |||
8682 | Fielding, et al. Standards Track [Page 155] | ||
8683 | |||
8684 | RFC 2616 HTTP/1.1 June 1999 | ||
8685 | |||
8686 | |||
8687 | Caching proxies provide additional potential vulnerabilities, since | ||
8688 | the contents of the cache represent an attractive target for | ||
8689 | malicious exploitation. Because cache contents persist after an HTTP | ||
8690 | request is complete, an attack on the cache can reveal information | ||
8691 | long after a user believes that the information has been removed from | ||
8692 | the network. Therefore, cache contents should be protected as | ||
8693 | sensitive information. | ||
8694 | |||
8695 | Proxy implementors should consider the privacy and security | ||
8696 | implications of their design and coding decisions, and of the | ||
8697 | configuration options they provide to proxy operators (especially the | ||
8698 | default configuration). | ||
8699 | |||
8700 | Users of a proxy need to be aware that they are no trustworthier than | ||
8701 | the people who run the proxy; HTTP itself cannot solve this problem. | ||
8702 | |||
8703 | The judicious use of cryptography, when appropriate, may suffice to | ||
8704 | protect against a broad range of security and privacy attacks. Such | ||
8705 | cryptography is beyond the scope of the HTTP/1.1 specification. | ||
8706 | |||
8707 | 15.7.1 Denial of Service Attacks on Proxies | ||
8708 | |||
8709 | They exist. They are hard to defend against. Research continues. | ||
8710 | Beware. | ||
8711 | |||
8712 | 16 Acknowledgments | ||
8713 | |||
8714 | This specification makes heavy use of the augmented BNF and generic | ||
8715 | constructs defined by David H. Crocker for RFC 822 [9]. Similarly, it | ||
8716 | reuses many of the definitions provided by Nathaniel Borenstein and | ||
8717 | Ned Freed for MIME [7]. We hope that their inclusion in this | ||
8718 | specification will help reduce past confusion over the relationship | ||
8719 | between HTTP and Internet mail message formats. | ||
8720 | |||
8721 | The HTTP protocol has evolved considerably over the years. It has | ||
8722 | benefited from a large and active developer community--the many | ||
8723 | people who have participated on the www-talk mailing list--and it is | ||
8724 | that community which has been most responsible for the success of | ||
8725 | HTTP and of the World-Wide Web in general. Marc Andreessen, Robert | ||
8726 | Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois | ||
8727 | Groff, Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob | ||
8728 | McCool, Lou Montulli, Dave Raggett, Tony Sanders, and Marc | ||
8729 | VanHeyningen deserve special recognition for their efforts in | ||
8730 | defining early aspects of the protocol. | ||
8731 | |||
8732 | This document has benefited greatly from the comments of all those | ||
8733 | participating in the HTTP-WG. In addition to those already mentioned, | ||
8734 | the following individuals have contributed to this specification: | ||
8735 | |||
8736 | |||
8737 | |||
8738 | Fielding, et al. Standards Track [Page 156] | ||
8739 | |||
8740 | RFC 2616 HTTP/1.1 June 1999 | ||
8741 | |||
8742 | |||
8743 | Gary Adams Ross Patterson | ||
8744 | Harald Tveit Alvestrand Albert Lunde | ||
8745 | Keith Ball John C. Mallery | ||
8746 | Brian Behlendorf Jean-Philippe Martin-Flatin | ||
8747 | Paul Burchard Mitra | ||
8748 | Maurizio Codogno David Morris | ||
8749 | Mike Cowlishaw Gavin Nicol | ||
8750 | Roman Czyborra Bill Perry | ||
8751 | Michael A. Dolan Jeffrey Perry | ||
8752 | David J. Fiander Scott Powers | ||
8753 | Alan Freier Owen Rees | ||
8754 | Marc Hedlund Luigi Rizzo | ||
8755 | Greg Herlihy David Robinson | ||
8756 | Koen Holtman Marc Salomon | ||
8757 | Alex Hopmann Rich Salz | ||
8758 | Bob Jernigan Allan M. Schiffman | ||
8759 | Shel Kaphan Jim Seidman | ||
8760 | Rohit Khare Chuck Shotton | ||
8761 | John Klensin Eric W. Sink | ||
8762 | Martijn Koster Simon E. Spero | ||
8763 | Alexei Kosut Richard N. Taylor | ||
8764 | David M. Kristol Robert S. Thau | ||
8765 | Daniel LaLiberte Bill (BearHeart) Weinman | ||
8766 | Ben Laurie Francois Yergeau | ||
8767 | Paul J. Leach Mary Ellen Zurko | ||
8768 | Daniel DuBois Josh Cohen | ||
8769 | |||
8770 | |||
8771 | Much of the content and presentation of the caching design is due to | ||
8772 | suggestions and comments from individuals including: Shel Kaphan, | ||
8773 | Paul Leach, Koen Holtman, David Morris, and Larry Masinter. | ||
8774 | |||
8775 | Most of the specification of ranges is based on work originally done | ||
8776 | by Ari Luotonen and John Franks, with additional input from Steve | ||
8777 | Zilles. | ||
8778 | |||
8779 | Thanks to the "cave men" of Palo Alto. You know who you are. | ||
8780 | |||
8781 | Jim Gettys (the current editor of this document) wishes particularly | ||
8782 | to thank Roy Fielding, the previous editor of this document, along | ||
8783 | with John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen | ||
8784 | Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, and | ||
8785 | Larry Masinter for their help. And thanks go particularly to Jeff | ||
8786 | Mogul and Scott Lawrence for performing the "MUST/MAY/SHOULD" audit. | ||
8787 | |||
8788 | |||
8789 | |||
8790 | |||
8791 | |||
8792 | |||
8793 | |||
8794 | Fielding, et al. Standards Track [Page 157] | ||
8795 | |||
8796 | RFC 2616 HTTP/1.1 June 1999 | ||
8797 | |||
8798 | |||
8799 | The Apache Group, Anselm Baird-Smith, author of Jigsaw, and Henrik | ||
8800 | Frystyk implemented RFC 2068 early, and we wish to thank them for the | ||
8801 | discovery of many of the problems that this document attempts to | ||
8802 | rectify. | ||
8803 | |||
8804 | 17 References | ||
8805 | |||
8806 | [1] Alvestrand, H., "Tags for the Identification of Languages", RFC | ||
8807 | 1766, March 1995. | ||
8808 | |||
8809 | [2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey, | ||
8810 | D. and B. Alberti, "The Internet Gopher Protocol (a distributed | ||
8811 | document search and retrieval protocol)", RFC 1436, March 1993. | ||
8812 | |||
8813 | [3] Berners-Lee, T., "Universal Resource Identifiers in WWW", RFC | ||
8814 | 1630, June 1994. | ||
8815 | |||
8816 | [4] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource | ||
8817 | Locators (URL)", RFC 1738, December 1994. | ||
8818 | |||
8819 | [5] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language - | ||
8820 | 2.0", RFC 1866, November 1995. | ||
8821 | |||
8822 | [6] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer | ||
8823 | Protocol -- HTTP/1.0", RFC 1945, May 1996. | ||
8824 | |||
8825 | [7] Freed, N. and N. Borenstein, "Multipurpose Internet Mail | ||
8826 | Extensions (MIME) Part One: Format of Internet Message Bodies", | ||
8827 | RFC 2045, November 1996. | ||
8828 | |||
8829 | [8] Braden, R., "Requirements for Internet Hosts -- Communication | ||
8830 | Layers", STD 3, RFC 1123, October 1989. | ||
8831 | |||
8832 | [9] Crocker, D., "Standard for The Format of ARPA Internet Text | ||
8833 | Messages", STD 11, RFC 822, August 1982. | ||
8834 | |||
8835 | [10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R., | ||
8836 | Sui, J., and M. Grinbaum, "WAIS Interface Protocol Prototype | ||
8837 | Functional Specification," (v1.5), Thinking Machines | ||
8838 | Corporation, April 1990. | ||
8839 | |||
8840 | [11] Fielding, R., "Relative Uniform Resource Locators", RFC 1808, | ||
8841 | June 1995. | ||
8842 | |||
8843 | [12] Horton, M. and R. Adams, "Standard for Interchange of USENET | ||
8844 | Messages", RFC 1036, December 1987. | ||
8845 | |||
8846 | |||
8847 | |||
8848 | |||
8849 | |||
8850 | Fielding, et al. Standards Track [Page 158] | ||
8851 | |||
8852 | RFC 2616 HTTP/1.1 June 1999 | ||
8853 | |||
8854 | |||
8855 | [13] Kantor, B. and P. Lapsley, "Network News Transfer Protocol", RFC | ||
8856 | 977, February 1986. | ||
8857 | |||
8858 | [14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part | ||
8859 | Three: Message Header Extensions for Non-ASCII Text", RFC 2047, | ||
8860 | November 1996. | ||
8861 | |||
8862 | [15] Nebel, E. and L. Masinter, "Form-based File Upload in HTML", RFC | ||
8863 | 1867, November 1995. | ||
8864 | |||
8865 | [16] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, | ||
8866 | August 1982. | ||
8867 | |||
8868 | [17] Postel, J., "Media Type Registration Procedure", RFC 1590, | ||
8869 | November 1996. | ||
8870 | |||
8871 | [18] Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC | ||
8872 | 959, October 1985. | ||
8873 | |||
8874 | [19] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, RFC 1700, | ||
8875 | October 1994. | ||
8876 | |||
8877 | [20] Sollins, K. and L. Masinter, "Functional Requirements for | ||
8878 | Uniform Resource Names", RFC 1737, December 1994. | ||
8879 | |||
8880 | [21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for | ||
8881 | Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986. | ||
8882 | |||
8883 | [22] ISO-8859. International Standard -- Information Processing -- | ||
8884 | 8-bit Single-Byte Coded Graphic Character Sets -- | ||
8885 | Part 1: Latin alphabet No. 1, ISO-8859-1:1987. | ||
8886 | Part 2: Latin alphabet No. 2, ISO-8859-2, 1987. | ||
8887 | Part 3: Latin alphabet No. 3, ISO-8859-3, 1988. | ||
8888 | Part 4: Latin alphabet No. 4, ISO-8859-4, 1988. | ||
8889 | Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988. | ||
8890 | Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987. | ||
8891 | Part 7: Latin/Greek alphabet, ISO-8859-7, 1987. | ||
8892 | Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988. | ||
8893 | Part 9: Latin alphabet No. 5, ISO-8859-9, 1990. | ||
8894 | |||
8895 | [23] Meyers, J. and M. Rose, "The Content-MD5 Header Field", RFC | ||
8896 | 1864, October 1995. | ||
8897 | |||
8898 | [24] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC | ||
8899 | 1900, February 1996. | ||
8900 | |||
8901 | [25] Deutsch, P., "GZIP file format specification version 4.3", RFC | ||
8902 | 1952, May 1996. | ||
8903 | |||
8904 | |||
8905 | |||
8906 | Fielding, et al. Standards Track [Page 159] | ||
8907 | |||
8908 | RFC 2616 HTTP/1.1 June 1999 | ||
8909 | |||
8910 | |||
8911 | [26] Venkata N. Padmanabhan, and Jeffrey C. Mogul. "Improving HTTP | ||
8912 | Latency", Computer Networks and ISDN Systems, v. 28, pp. 25-35, | ||
8913 | Dec. 1995. Slightly revised version of paper in Proc. 2nd | ||
8914 | International WWW Conference '94: Mosaic and the Web, Oct. 1994, | ||
8915 | which is available at | ||
8916 | http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat | ||
8917 | ency.html. | ||
8918 | |||
8919 | [27] Joe Touch, John Heidemann, and Katia Obraczka. "Analysis of HTTP | ||
8920 | Performance", <URL: http://www.isi.edu/touch/pubs/http-perf96/>, | ||
8921 | ISI Research Report ISI/RR-98-463, (original report dated Aug. | ||
8922 | 1996), USC/Information Sciences Institute, August 1998. | ||
8923 | |||
8924 | [28] Mills, D., "Network Time Protocol (Version 3) Specification, | ||
8925 | Implementation and Analysis", RFC 1305, March 1992. | ||
8926 | |||
8927 | [29] Deutsch, P., "DEFLATE Compressed Data Format Specification | ||
8928 | version 1.3", RFC 1951, May 1996. | ||
8929 | |||
8930 | [30] S. Spero, "Analysis of HTTP Performance Problems," | ||
8931 | http://sunsite.unc.edu/mdma-release/http-prob.html. | ||
8932 | |||
8933 | [31] Deutsch, P. and J. Gailly, "ZLIB Compressed Data Format | ||
8934 | Specification version 3.3", RFC 1950, May 1996. | ||
8935 | |||
8936 | [32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P., | ||
8937 | Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP: | ||
8938 | Digest Access Authentication", RFC 2069, January 1997. | ||
8939 | |||
8940 | [33] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T. | ||
8941 | Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC | ||
8942 | 2068, January 1997. | ||
8943 | |||
8944 | [34] Bradner, S., "Key words for use in RFCs to Indicate Requirement | ||
8945 | Levels", BCP 14, RFC 2119, March 1997. | ||
8946 | |||
8947 | [35] Troost, R. and Dorner, S., "Communicating Presentation | ||
8948 | Information in Internet Messages: The Content-Disposition | ||
8949 | Header", RFC 1806, June 1995. | ||
8950 | |||
8951 | [36] Mogul, J., Fielding, R., Gettys, J. and H. Frystyk, "Use and | ||
8952 | Interpretation of HTTP Version Numbers", RFC 2145, May 1997. | ||
8953 | [jg639] | ||
8954 | |||
8955 | [37] Palme, J., "Common Internet Message Headers", RFC 2076, February | ||
8956 | 1997. [jg640] | ||
8957 | |||
8958 | |||
8959 | |||
8960 | |||
8961 | |||
8962 | Fielding, et al. Standards Track [Page 160] | ||
8963 | |||
8964 | RFC 2616 HTTP/1.1 June 1999 | ||
8965 | |||
8966 | |||
8967 | [38] Yergeau, F., "UTF-8, a transformation format of Unicode and | ||
8968 | ISO-10646", RFC 2279, January 1998. [jg641] | ||
8969 | |||
8970 | [39] Nielsen, H.F., Gettys, J., Baird-Smith, A., Prud'hommeaux, E., | ||
8971 | Lie, H., and C. Lilley. "Network Performance Effects of | ||
8972 | HTTP/1.1, CSS1, and PNG," Proceedings of ACM SIGCOMM '97, Cannes | ||
8973 | France, September 1997.[jg642] | ||
8974 | |||
8975 | [40] Freed, N. and N. Borenstein, "Multipurpose Internet Mail | ||
8976 | Extensions (MIME) Part Two: Media Types", RFC 2046, November | ||
8977 | 1996. [jg643] | ||
8978 | |||
8979 | [41] Alvestrand, H., "IETF Policy on Character Sets and Languages", | ||
8980 | BCP 18, RFC 2277, January 1998. [jg644] | ||
8981 | |||
8982 | [42] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource | ||
8983 | Identifiers (URI): Generic Syntax and Semantics", RFC 2396, | ||
8984 | August 1998. [jg645] | ||
8985 | |||
8986 | [43] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., | ||
8987 | Leach, P., Luotonen, A., Sink, E. and L. Stewart, "HTTP | ||
8988 | Authentication: Basic and Digest Access Authentication", RFC | ||
8989 | 2617, June 1999. [jg646] | ||
8990 | |||
8991 | [44] Luotonen, A., "Tunneling TCP based protocols through Web proxy | ||
8992 | servers," Work in Progress. [jg647] | ||
8993 | |||
8994 | [45] Palme, J. and A. Hopmann, "MIME E-mail Encapsulation of | ||
8995 | Aggregate Documents, such as HTML (MHTML)", RFC 2110, March | ||
8996 | 1997. | ||
8997 | |||
8998 | [46] Bradner, S., "The Internet Standards Process -- Revision 3", BCP | ||
8999 | 9, RFC 2026, October 1996. | ||
9000 | |||
9001 | [47] Masinter, L., "Hyper Text Coffee Pot Control Protocol | ||
9002 | (HTCPCP/1.0)", RFC 2324, 1 April 1998. | ||
9003 | |||
9004 | [48] Freed, N. and N. Borenstein, "Multipurpose Internet Mail | ||
9005 | Extensions (MIME) Part Five: Conformance Criteria and Examples", | ||
9006 | RFC 2049, November 1996. | ||
9007 | |||
9008 | [49] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation | ||
9009 | Information in Internet Messages: The Content-Disposition Header | ||
9010 | Field", RFC 2183, August 1997. | ||
9011 | |||
9012 | |||
9013 | |||
9014 | |||
9015 | |||
9016 | |||
9017 | |||
9018 | Fielding, et al. Standards Track [Page 161] | ||
9019 | |||
9020 | RFC 2616 HTTP/1.1 June 1999 | ||
9021 | |||
9022 | |||
9023 | 18 Authors' Addresses | ||
9024 | |||
9025 | Roy T. Fielding | ||
9026 | Information and Computer Science | ||
9027 | University of California, Irvine | ||
9028 | Irvine, CA 92697-3425, USA | ||
9029 | |||
9030 | Fax: +1 (949) 824-1715 | ||
9031 | EMail: fielding@ics.uci.edu | ||
9032 | |||
9033 | |||
9034 | James Gettys | ||
9035 | World Wide Web Consortium | ||
9036 | MIT Laboratory for Computer Science | ||
9037 | 545 Technology Square | ||
9038 | Cambridge, MA 02139, USA | ||
9039 | |||
9040 | Fax: +1 (617) 258 8682 | ||
9041 | EMail: jg@w3.org | ||
9042 | |||
9043 | |||
9044 | Jeffrey C. Mogul | ||
9045 | Western Research Laboratory | ||
9046 | Compaq Computer Corporation | ||
9047 | 250 University Avenue | ||
9048 | Palo Alto, California, 94305, USA | ||
9049 | |||
9050 | EMail: mogul@wrl.dec.com | ||
9051 | |||
9052 | |||
9053 | Henrik Frystyk Nielsen | ||
9054 | World Wide Web Consortium | ||
9055 | MIT Laboratory for Computer Science | ||
9056 | 545 Technology Square | ||
9057 | Cambridge, MA 02139, USA | ||
9058 | |||
9059 | Fax: +1 (617) 258 8682 | ||
9060 | EMail: frystyk@w3.org | ||
9061 | |||
9062 | |||
9063 | Larry Masinter | ||
9064 | Xerox Corporation | ||
9065 | 3333 Coyote Hill Road | ||
9066 | Palo Alto, CA 94034, USA | ||
9067 | |||
9068 | EMail: masinter@parc.xerox.com | ||
9069 | |||
9070 | |||
9071 | |||
9072 | |||
9073 | |||
9074 | Fielding, et al. Standards Track [Page 162] | ||
9075 | |||
9076 | RFC 2616 HTTP/1.1 June 1999 | ||
9077 | |||
9078 | |||
9079 | Paul J. Leach | ||
9080 | Microsoft Corporation | ||
9081 | 1 Microsoft Way | ||
9082 | Redmond, WA 98052, USA | ||
9083 | |||
9084 | EMail: paulle@microsoft.com | ||
9085 | |||
9086 | |||
9087 | Tim Berners-Lee | ||
9088 | Director, World Wide Web Consortium | ||
9089 | MIT Laboratory for Computer Science | ||
9090 | 545 Technology Square | ||
9091 | Cambridge, MA 02139, USA | ||
9092 | |||
9093 | Fax: +1 (617) 258 8682 | ||
9094 | EMail: timbl@w3.org | ||
9095 | |||
9096 | |||
9097 | |||
9098 | |||
9099 | |||
9100 | |||
9101 | |||
9102 | |||
9103 | |||
9104 | |||
9105 | |||
9106 | |||
9107 | |||
9108 | |||
9109 | |||
9110 | |||
9111 | |||
9112 | |||
9113 | |||
9114 | |||
9115 | |||
9116 | |||
9117 | |||
9118 | |||
9119 | |||
9120 | |||
9121 | |||
9122 | |||
9123 | |||
9124 | |||
9125 | |||
9126 | |||
9127 | |||
9128 | |||
9129 | |||
9130 | Fielding, et al. Standards Track [Page 163] | ||
9131 | |||
9132 | RFC 2616 HTTP/1.1 June 1999 | ||
9133 | |||
9134 | |||
9135 | 19 Appendices | ||
9136 | |||
9137 | 19.1 Internet Media Type message/http and application/http | ||
9138 | |||
9139 | In addition to defining the HTTP/1.1 protocol, this document serves | ||
9140 | as the specification for the Internet media type "message/http" and | ||
9141 | "application/http". The message/http type can be used to enclose a | ||
9142 | single HTTP request or response message, provided that it obeys the | ||
9143 | MIME restrictions for all "message" types regarding line length and | ||
9144 | encodings. The application/http type can be used to enclose a | ||
9145 | pipeline of one or more HTTP request or response messages (not | ||
9146 | intermixed). The following is to be registered with IANA [17]. | ||
9147 | |||
9148 | Media Type name: message | ||
9149 | Media subtype name: http | ||
9150 | Required parameters: none | ||
9151 | Optional parameters: version, msgtype | ||
9152 | version: The HTTP-Version number of the enclosed message | ||
9153 | (e.g., "1.1"). If not present, the version can be | ||
9154 | determined from the first line of the body. | ||
9155 | msgtype: The message type -- "request" or "response". If not | ||
9156 | present, the type can be determined from the first | ||
9157 | line of the body. | ||
9158 | Encoding considerations: only "7bit", "8bit", or "binary" are | ||
9159 | permitted | ||
9160 | Security considerations: none | ||
9161 | |||
9162 | Media Type name: application | ||
9163 | Media subtype name: http | ||
9164 | Required parameters: none | ||
9165 | Optional parameters: version, msgtype | ||
9166 | version: The HTTP-Version number of the enclosed messages | ||
9167 | (e.g., "1.1"). If not present, the version can be | ||
9168 | determined from the first line of the body. | ||
9169 | msgtype: The message type -- "request" or "response". If not | ||
9170 | present, the type can be determined from the first | ||
9171 | line of the body. | ||
9172 | Encoding considerations: HTTP messages enclosed by this type | ||
9173 | are in "binary" format; use of an appropriate | ||
9174 | Content-Transfer-Encoding is required when | ||
9175 | transmitted via E-mail. | ||
9176 | Security considerations: none | ||
9177 | |||
9178 | |||
9179 | |||
9180 | |||
9181 | |||
9182 | |||
9183 | |||
9184 | |||
9185 | |||
9186 | Fielding, et al. Standards Track [Page 164] | ||
9187 | |||
9188 | RFC 2616 HTTP/1.1 June 1999 | ||
9189 | |||
9190 | |||
9191 | 19.2 Internet Media Type multipart/byteranges | ||
9192 | |||
9193 | When an HTTP 206 (Partial Content) response message includes the | ||
9194 | content of multiple ranges (a response to a request for multiple | ||
9195 | non-overlapping ranges), these are transmitted as a multipart | ||
9196 | message-body. The media type for this purpose is called | ||
9197 | "multipart/byteranges". | ||
9198 | |||
9199 | The multipart/byteranges media type includes two or more parts, each | ||
9200 | with its own Content-Type and Content-Range fields. The required | ||
9201 | boundary parameter specifies the boundary string used to separate | ||
9202 | each body-part. | ||
9203 | |||
9204 | Media Type name: multipart | ||
9205 | Media subtype name: byteranges | ||
9206 | Required parameters: boundary | ||
9207 | Optional parameters: none | ||
9208 | Encoding considerations: only "7bit", "8bit", or "binary" are | ||
9209 | permitted | ||
9210 | Security considerations: none | ||
9211 | |||
9212 | |||
9213 | For example: | ||
9214 | |||
9215 | HTTP/1.1 206 Partial Content | ||
9216 | Date: Wed, 15 Nov 1995 06:25:24 GMT | ||
9217 | Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT | ||
9218 | Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES | ||
9219 | |||
9220 | --THIS_STRING_SEPARATES | ||
9221 | Content-type: application/pdf | ||
9222 | Content-range: bytes 500-999/8000 | ||
9223 | |||
9224 | ...the first range... | ||
9225 | --THIS_STRING_SEPARATES | ||
9226 | Content-type: application/pdf | ||
9227 | Content-range: bytes 7000-7999/8000 | ||
9228 | |||
9229 | ...the second range | ||
9230 | --THIS_STRING_SEPARATES-- | ||
9231 | |||
9232 | Notes: | ||
9233 | |||
9234 | 1) Additional CRLFs may precede the first boundary string in the | ||
9235 | entity. | ||
9236 | |||
9237 | |||
9238 | |||
9239 | |||
9240 | |||
9241 | |||
9242 | Fielding, et al. Standards Track [Page 165] | ||
9243 | |||
9244 | RFC 2616 HTTP/1.1 June 1999 | ||
9245 | |||
9246 | |||
9247 | 2) Although RFC 2046 [40] permits the boundary string to be | ||
9248 | quoted, some existing implementations handle a quoted boundary | ||
9249 | string incorrectly. | ||
9250 | |||
9251 | 3) A number of browsers and servers were coded to an early draft | ||
9252 | of the byteranges specification to use a media type of | ||
9253 | multipart/x-byteranges, which is almost, but not quite | ||
9254 | compatible with the version documented in HTTP/1.1. | ||
9255 | |||
9256 | 19.3 Tolerant Applications | ||
9257 | |||
9258 | Although this document specifies the requirements for the generation | ||
9259 | of HTTP/1.1 messages, not all applications will be correct in their | ||
9260 | implementation. We therefore recommend that operational applications | ||
9261 | be tolerant of deviations whenever those deviations can be | ||
9262 | interpreted unambiguously. | ||
9263 | |||
9264 | Clients SHOULD be tolerant in parsing the Status-Line and servers | ||
9265 | tolerant when parsing the Request-Line. In particular, they SHOULD | ||
9266 | accept any amount of SP or HT characters between fields, even though | ||
9267 | only a single SP is required. | ||
9268 | |||
9269 | The line terminator for message-header fields is the sequence CRLF. | ||
9270 | However, we recommend that applications, when parsing such headers, | ||
9271 | recognize a single LF as a line terminator and ignore the leading CR. | ||
9272 | |||
9273 | The character set of an entity-body SHOULD be labeled as the lowest | ||
9274 | common denominator of the character codes used within that body, with | ||
9275 | the exception that not labeling the entity is preferred over labeling | ||
9276 | the entity with the labels US-ASCII or ISO-8859-1. See section 3.7.1 | ||
9277 | and 3.4.1. | ||
9278 | |||
9279 | Additional rules for requirements on parsing and encoding of dates | ||
9280 | and other potential problems with date encodings include: | ||
9281 | |||
9282 | - HTTP/1.1 clients and caches SHOULD assume that an RFC-850 date | ||
9283 | which appears to be more than 50 years in the future is in fact | ||
9284 | in the past (this helps solve the "year 2000" problem). | ||
9285 | |||
9286 | - An HTTP/1.1 implementation MAY internally represent a parsed | ||
9287 | Expires date as earlier than the proper value, but MUST NOT | ||
9288 | internally represent a parsed Expires date as later than the | ||
9289 | proper value. | ||
9290 | |||
9291 | - All expiration-related calculations MUST be done in GMT. The | ||
9292 | local time zone MUST NOT influence the calculation or comparison | ||
9293 | of an age or expiration time. | ||
9294 | |||
9295 | |||
9296 | |||
9297 | |||
9298 | Fielding, et al. Standards Track [Page 166] | ||
9299 | |||
9300 | RFC 2616 HTTP/1.1 June 1999 | ||
9301 | |||
9302 | |||
9303 | - If an HTTP header incorrectly carries a date value with a time | ||
9304 | zone other than GMT, it MUST be converted into GMT using the | ||
9305 | most conservative possible conversion. | ||
9306 | |||
9307 | 19.4 Differences Between HTTP Entities and RFC 2045 Entities | ||
9308 | |||
9309 | HTTP/1.1 uses many of the constructs defined for Internet Mail (RFC | ||
9310 | 822 [9]) and the Multipurpose Internet Mail Extensions (MIME [7]) to | ||
9311 | allow entities to be transmitted in an open variety of | ||
9312 | representations and with extensible mechanisms. However, RFC 2045 | ||
9313 | discusses mail, and HTTP has a few features that are different from | ||
9314 | those described in RFC 2045. These differences were carefully chosen | ||
9315 | to optimize performance over binary connections, to allow greater | ||
9316 | freedom in the use of new media types, to make date comparisons | ||
9317 | easier, and to acknowledge the practice of some early HTTP servers | ||
9318 | and clients. | ||
9319 | |||
9320 | This appendix describes specific areas where HTTP differs from RFC | ||
9321 | 2045. Proxies and gateways to strict MIME environments SHOULD be | ||
9322 | aware of these differences and provide the appropriate conversions | ||
9323 | where necessary. Proxies and gateways from MIME environments to HTTP | ||
9324 | also need to be aware of the differences because some conversions | ||
9325 | might be required. | ||
9326 | |||
9327 | 19.4.1 MIME-Version | ||
9328 | |||
9329 | HTTP is not a MIME-compliant protocol. However, HTTP/1.1 messages MAY | ||
9330 | include a single MIME-Version general-header field to indicate what | ||
9331 | version of the MIME protocol was used to construct the message. Use | ||
9332 | of the MIME-Version header field indicates that the message is in | ||
9333 | full compliance with the MIME protocol (as defined in RFC 2045[7]). | ||
9334 | Proxies/gateways are responsible for ensuring full compliance (where | ||
9335 | possible) when exporting HTTP messages to strict MIME environments. | ||
9336 | |||
9337 | MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT | ||
9338 | |||
9339 | MIME version "1.0" is the default for use in HTTP/1.1. However, | ||
9340 | HTTP/1.1 message parsing and semantics are defined by this document | ||
9341 | and not the MIME specification. | ||
9342 | |||
9343 | 19.4.2 Conversion to Canonical Form | ||
9344 | |||
9345 | RFC 2045 [7] requires that an Internet mail entity be converted to | ||
9346 | canonical form prior to being transferred, as described in section 4 | ||
9347 | of RFC 2049 [48]. Section 3.7.1 of this document describes the forms | ||
9348 | allowed for subtypes of the "text" media type when transmitted over | ||
9349 | HTTP. RFC 2046 requires that content with a type of "text" represent | ||
9350 | line breaks as CRLF and forbids the use of CR or LF outside of line | ||
9351 | |||
9352 | |||
9353 | |||
9354 | Fielding, et al. Standards Track [Page 167] | ||
9355 | |||
9356 | RFC 2616 HTTP/1.1 June 1999 | ||
9357 | |||
9358 | |||
9359 | break sequences. HTTP allows CRLF, bare CR, and bare LF to indicate a | ||
9360 | line break within text content when a message is transmitted over | ||
9361 | HTTP. | ||
9362 | |||
9363 | Where it is possible, a proxy or gateway from HTTP to a strict MIME | ||
9364 | environment SHOULD translate all line breaks within the text media | ||
9365 | types described in section 3.7.1 of this document to the RFC 2049 | ||
9366 | canonical form of CRLF. Note, however, that this might be complicated | ||
9367 | by the presence of a Content-Encoding and by the fact that HTTP | ||
9368 | allows the use of some character sets which do not use octets 13 and | ||
9369 | 10 to represent CR and LF, as is the case for some multi-byte | ||
9370 | character sets. | ||
9371 | |||
9372 | Implementors should note that conversion will break any cryptographic | ||
9373 | checksums applied to the original content unless the original content | ||
9374 | is already in canonical form. Therefore, the canonical form is | ||
9375 | recommended for any content that uses such checksums in HTTP. | ||
9376 | |||
9377 | 19.4.3 Conversion of Date Formats | ||
9378 | |||
9379 | HTTP/1.1 uses a restricted set of date formats (section 3.3.1) to | ||
9380 | simplify the process of date comparison. Proxies and gateways from | ||
9381 | other protocols SHOULD ensure that any Date header field present in a | ||
9382 | message conforms to one of the HTTP/1.1 formats and rewrite the date | ||
9383 | if necessary. | ||
9384 | |||
9385 | 19.4.4 Introduction of Content-Encoding | ||
9386 | |||
9387 | RFC 2045 does not include any concept equivalent to HTTP/1.1's | ||
9388 | Content-Encoding header field. Since this acts as a modifier on the | ||
9389 | media type, proxies and gateways from HTTP to MIME-compliant | ||
9390 | protocols MUST either change the value of the Content-Type header | ||
9391 | field or decode the entity-body before forwarding the message. (Some | ||
9392 | experimental applications of Content-Type for Internet mail have used | ||
9393 | a media-type parameter of ";conversions=<content-coding>" to perform | ||
9394 | a function equivalent to Content-Encoding. However, this parameter is | ||
9395 | not part of RFC 2045.) | ||
9396 | |||
9397 | 19.4.5 No Content-Transfer-Encoding | ||
9398 | |||
9399 | HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC | ||
9400 | 2045. Proxies and gateways from MIME-compliant protocols to HTTP MUST | ||
9401 | remove any non-identity CTE ("quoted-printable" or "base64") encoding | ||
9402 | prior to delivering the response message to an HTTP client. | ||
9403 | |||
9404 | Proxies and gateways from HTTP to MIME-compliant protocols are | ||
9405 | responsible for ensuring that the message is in the correct format | ||
9406 | and encoding for safe transport on that protocol, where "safe | ||
9407 | |||
9408 | |||
9409 | |||
9410 | Fielding, et al. Standards Track [Page 168] | ||
9411 | |||
9412 | RFC 2616 HTTP/1.1 June 1999 | ||
9413 | |||
9414 | |||
9415 | transport" is defined by the limitations of the protocol being used. | ||
9416 | Such a proxy or gateway SHOULD label the data with an appropriate | ||
9417 | Content-Transfer-Encoding if doing so will improve the likelihood of | ||
9418 | safe transport over the destination protocol. | ||
9419 | |||
9420 | 19.4.6 Introduction of Transfer-Encoding | ||
9421 | |||
9422 | HTTP/1.1 introduces the Transfer-Encoding header field (section | ||
9423 | 14.41). Proxies/gateways MUST remove any transfer-coding prior to | ||
9424 | forwarding a message via a MIME-compliant protocol. | ||
9425 | |||
9426 | A process for decoding the "chunked" transfer-coding (section 3.6) | ||
9427 | can be represented in pseudo-code as: | ||
9428 | |||
9429 | length := 0 | ||
9430 | read chunk-size, chunk-extension (if any) and CRLF | ||
9431 | while (chunk-size > 0) { | ||
9432 | read chunk-data and CRLF | ||
9433 | append chunk-data to entity-body | ||
9434 | length := length + chunk-size | ||
9435 | read chunk-size and CRLF | ||
9436 | } | ||
9437 | read entity-header | ||
9438 | while (entity-header not empty) { | ||
9439 | append entity-header to existing header fields | ||
9440 | read entity-header | ||
9441 | } | ||
9442 | Content-Length := length | ||
9443 | Remove "chunked" from Transfer-Encoding | ||
9444 | |||
9445 | 19.4.7 MHTML and Line Length Limitations | ||
9446 | |||
9447 | HTTP implementations which share code with MHTML [45] implementations | ||
9448 | need to be aware of MIME line length limitations. Since HTTP does not | ||
9449 | have this limitation, HTTP does not fold long lines. MHTML messages | ||
9450 | being transported by HTTP follow all conventions of MHTML, including | ||
9451 | line length limitations and folding, canonicalization, etc., since | ||
9452 | HTTP transports all message-bodies as payload (see section 3.7.2) and | ||
9453 | does not interpret the content or any MIME header lines that might be | ||
9454 | contained therein. | ||
9455 | |||
9456 | 19.5 Additional Features | ||
9457 | |||
9458 | RFC 1945 and RFC 2068 document protocol elements used by some | ||
9459 | existing HTTP implementations, but not consistently and correctly | ||
9460 | across most HTTP/1.1 applications. Implementors are advised to be | ||
9461 | aware of these features, but cannot rely upon their presence in, or | ||
9462 | interoperability with, other HTTP/1.1 applications. Some of these | ||
9463 | |||
9464 | |||
9465 | |||
9466 | Fielding, et al. Standards Track [Page 169] | ||
9467 | |||
9468 | RFC 2616 HTTP/1.1 June 1999 | ||
9469 | |||
9470 | |||
9471 | describe proposed experimental features, and some describe features | ||
9472 | that experimental deployment found lacking that are now addressed in | ||
9473 | the base HTTP/1.1 specification. | ||
9474 | |||
9475 | A number of other headers, such as Content-Disposition and Title, | ||
9476 | from SMTP and MIME are also often implemented (see RFC 2076 [37]). | ||
9477 | |||
9478 | 19.5.1 Content-Disposition | ||
9479 | |||
9480 | The Content-Disposition response-header field has been proposed as a | ||
9481 | means for the origin server to suggest a default filename if the user | ||
9482 | requests that the content is saved to a file. This usage is derived | ||
9483 | from the definition of Content-Disposition in RFC 1806 [35]. | ||
9484 | |||
9485 | content-disposition = "Content-Disposition" ":" | ||
9486 | disposition-type *( ";" disposition-parm ) | ||
9487 | disposition-type = "attachment" | disp-extension-token | ||
9488 | disposition-parm = filename-parm | disp-extension-parm | ||
9489 | filename-parm = "filename" "=" quoted-string | ||
9490 | disp-extension-token = token | ||
9491 | disp-extension-parm = token "=" ( token | quoted-string ) | ||
9492 | |||
9493 | An example is | ||
9494 | |||
9495 | Content-Disposition: attachment; filename="fname.ext" | ||
9496 | |||
9497 | The receiving user agent SHOULD NOT respect any directory path | ||
9498 | information present in the filename-parm parameter, which is the only | ||
9499 | parameter believed to apply to HTTP implementations at this time. The | ||
9500 | filename SHOULD be treated as a terminal component only. | ||
9501 | |||
9502 | If this header is used in a response with the application/octet- | ||
9503 | stream content-type, the implied suggestion is that the user agent | ||
9504 | should not display the response, but directly enter a `save response | ||
9505 | as...' dialog. | ||
9506 | |||
9507 | See section 15.5 for Content-Disposition security issues. | ||
9508 | |||
9509 | 19.6 Compatibility with Previous Versions | ||
9510 | |||
9511 | It is beyond the scope of a protocol specification to mandate | ||
9512 | compliance with previous versions. HTTP/1.1 was deliberately | ||
9513 | designed, however, to make supporting previous versions easy. It is | ||
9514 | worth noting that, at the time of composing this specification | ||
9515 | (1996), we would expect commercial HTTP/1.1 servers to: | ||
9516 | |||
9517 | - recognize the format of the Request-Line for HTTP/0.9, 1.0, and | ||
9518 | 1.1 requests; | ||
9519 | |||
9520 | |||
9521 | |||
9522 | Fielding, et al. Standards Track [Page 170] | ||
9523 | |||
9524 | RFC 2616 HTTP/1.1 June 1999 | ||
9525 | |||
9526 | |||
9527 | - understand any valid request in the format of HTTP/0.9, 1.0, or | ||
9528 | 1.1; | ||
9529 | |||
9530 | - respond appropriately with a message in the same major version | ||
9531 | used by the client. | ||
9532 | |||
9533 | And we would expect HTTP/1.1 clients to: | ||
9534 | |||
9535 | - recognize the format of the Status-Line for HTTP/1.0 and 1.1 | ||
9536 | responses; | ||
9537 | |||
9538 | - understand any valid response in the format of HTTP/0.9, 1.0, or | ||
9539 | 1.1. | ||
9540 | |||
9541 | For most implementations of HTTP/1.0, each connection is established | ||
9542 | by the client prior to the request and closed by the server after | ||
9543 | sending the response. Some implementations implement the Keep-Alive | ||
9544 | version of persistent connections described in section 19.7.1 of RFC | ||
9545 | 2068 [33]. | ||
9546 | |||
9547 | 19.6.1 Changes from HTTP/1.0 | ||
9548 | |||
9549 | This section summarizes major differences between versions HTTP/1.0 | ||
9550 | and HTTP/1.1. | ||
9551 | |||
9552 | 19.6.1.1 Changes to Simplify Multi-homed Web Servers and Conserve IP | ||
9553 | Addresses | ||
9554 | |||
9555 | The requirements that clients and servers support the Host request- | ||
9556 | header, report an error if the Host request-header (section 14.23) is | ||
9557 | missing from an HTTP/1.1 request, and accept absolute URIs (section | ||
9558 | 5.1.2) are among the most important changes defined by this | ||
9559 | specification. | ||
9560 | |||
9561 | Older HTTP/1.0 clients assumed a one-to-one relationship of IP | ||
9562 | addresses and servers; there was no other established mechanism for | ||
9563 | distinguishing the intended server of a request than the IP address | ||
9564 | to which that request was directed. The changes outlined above will | ||
9565 | allow the Internet, once older HTTP clients are no longer common, to | ||
9566 | support multiple Web sites from a single IP address, greatly | ||
9567 | simplifying large operational Web servers, where allocation of many | ||
9568 | IP addresses to a single host has created serious problems. The | ||
9569 | Internet will also be able to recover the IP addresses that have been | ||
9570 | allocated for the sole purpose of allowing special-purpose domain | ||
9571 | names to be used in root-level HTTP URLs. Given the rate of growth of | ||
9572 | the Web, and the number of servers already deployed, it is extremely | ||
9573 | |||
9574 | |||
9575 | |||
9576 | |||
9577 | |||
9578 | Fielding, et al. Standards Track [Page 171] | ||
9579 | |||
9580 | RFC 2616 HTTP/1.1 June 1999 | ||
9581 | |||
9582 | |||
9583 | important that all implementations of HTTP (including updates to | ||
9584 | existing HTTP/1.0 applications) correctly implement these | ||
9585 | requirements: | ||
9586 | |||
9587 | - Both clients and servers MUST support the Host request-header. | ||
9588 | |||
9589 | - A client that sends an HTTP/1.1 request MUST send a Host header. | ||
9590 | |||
9591 | - Servers MUST report a 400 (Bad Request) error if an HTTP/1.1 | ||
9592 | request does not include a Host request-header. | ||
9593 | |||
9594 | - Servers MUST accept absolute URIs. | ||
9595 | |||
9596 | 19.6.2 Compatibility with HTTP/1.0 Persistent Connections | ||
9597 | |||
9598 | Some clients and servers might wish to be compatible with some | ||
9599 | previous implementations of persistent connections in HTTP/1.0 | ||
9600 | clients and servers. Persistent connections in HTTP/1.0 are | ||
9601 | explicitly negotiated as they are not the default behavior. HTTP/1.0 | ||
9602 | experimental implementations of persistent connections are faulty, | ||
9603 | and the new facilities in HTTP/1.1 are designed to rectify these | ||
9604 | problems. The problem was that some existing 1.0 clients may be | ||
9605 | sending Keep-Alive to a proxy server that doesn't understand | ||
9606 | Connection, which would then erroneously forward it to the next | ||
9607 | inbound server, which would establish the Keep-Alive connection and | ||
9608 | result in a hung HTTP/1.0 proxy waiting for the close on the | ||
9609 | response. The result is that HTTP/1.0 clients must be prevented from | ||
9610 | using Keep-Alive when talking to proxies. | ||
9611 | |||
9612 | However, talking to proxies is the most important use of persistent | ||
9613 | connections, so that prohibition is clearly unacceptable. Therefore, | ||
9614 | we need some other mechanism for indicating a persistent connection | ||
9615 | is desired, which is safe to use even when talking to an old proxy | ||
9616 | that ignores Connection. Persistent connections are the default for | ||
9617 | HTTP/1.1 messages; we introduce a new keyword (Connection: close) for | ||
9618 | declaring non-persistence. See section 14.10. | ||
9619 | |||
9620 | The original HTTP/1.0 form of persistent connections (the Connection: | ||
9621 | Keep-Alive and Keep-Alive header) is documented in RFC 2068. [33] | ||
9622 | |||
9623 | 19.6.3 Changes from RFC 2068 | ||
9624 | |||
9625 | This specification has been carefully audited to correct and | ||
9626 | disambiguate key word usage; RFC 2068 had many problems in respect to | ||
9627 | the conventions laid out in RFC 2119 [34]. | ||
9628 | |||
9629 | Clarified which error code should be used for inbound server failures | ||
9630 | (e.g. DNS failures). (Section 10.5.5). | ||
9631 | |||
9632 | |||
9633 | |||
9634 | Fielding, et al. Standards Track [Page 172] | ||
9635 | |||
9636 | RFC 2616 HTTP/1.1 June 1999 | ||
9637 | |||
9638 | |||
9639 | CREATE had a race that required an Etag be sent when a resource is | ||
9640 | first created. (Section 10.2.2). | ||
9641 | |||
9642 | Content-Base was deleted from the specification: it was not | ||
9643 | implemented widely, and there is no simple, safe way to introduce it | ||
9644 | without a robust extension mechanism. In addition, it is used in a | ||
9645 | similar, but not identical fashion in MHTML [45]. | ||
9646 | |||
9647 | Transfer-coding and message lengths all interact in ways that | ||
9648 | required fixing exactly when chunked encoding is used (to allow for | ||
9649 | transfer encoding that may not be self delimiting); it was important | ||
9650 | to straighten out exactly how message lengths are computed. (Sections | ||
9651 | 3.6, 4.4, 7.2.2, 13.5.2, 14.13, 14.16) | ||
9652 | |||
9653 | A content-coding of "identity" was introduced, to solve problems | ||
9654 | discovered in caching. (section 3.5) | ||
9655 | |||
9656 | Quality Values of zero should indicate that "I don't want something" | ||
9657 | to allow clients to refuse a representation. (Section 3.9) | ||
9658 | |||
9659 | The use and interpretation of HTTP version numbers has been clarified | ||
9660 | by RFC 2145. Require proxies to upgrade requests to highest protocol | ||
9661 | version they support to deal with problems discovered in HTTP/1.0 | ||
9662 | implementations (Section 3.1) | ||
9663 | |||
9664 | Charset wildcarding is introduced to avoid explosion of character set | ||
9665 | names in accept headers. (Section 14.2) | ||
9666 | |||
9667 | A case was missed in the Cache-Control model of HTTP/1.1; s-maxage | ||
9668 | was introduced to add this missing case. (Sections 13.4, 14.8, 14.9, | ||
9669 | 14.9.3) | ||
9670 | |||
9671 | The Cache-Control: max-age directive was not properly defined for | ||
9672 | responses. (Section 14.9.3) | ||
9673 | |||
9674 | There are situations where a server (especially a proxy) does not | ||
9675 | know the full length of a response but is capable of serving a | ||
9676 | byterange request. We therefore need a mechanism to allow byteranges | ||
9677 | with a content-range not indicating the full length of the message. | ||
9678 | (Section 14.16) | ||
9679 | |||
9680 | Range request responses would become very verbose if all meta-data | ||
9681 | were always returned; by allowing the server to only send needed | ||
9682 | headers in a 206 response, this problem can be avoided. (Section | ||
9683 | 10.2.7, 13.5.3, and 14.27) | ||
9684 | |||
9685 | |||
9686 | |||
9687 | |||
9688 | |||
9689 | |||
9690 | Fielding, et al. Standards Track [Page 173] | ||
9691 | |||
9692 | RFC 2616 HTTP/1.1 June 1999 | ||
9693 | |||
9694 | |||
9695 | Fix problem with unsatisfiable range requests; there are two cases: | ||
9696 | syntactic problems, and range doesn't exist in the document. The 416 | ||
9697 | status code was needed to resolve this ambiguity needed to indicate | ||
9698 | an error for a byte range request that falls outside of the actual | ||
9699 | contents of a document. (Section 10.4.17, 14.16) | ||
9700 | |||
9701 | Rewrite of message transmission requirements to make it much harder | ||
9702 | for implementors to get it wrong, as the consequences of errors here | ||
9703 | can have significant impact on the Internet, and to deal with the | ||
9704 | following problems: | ||
9705 | |||
9706 | 1. Changing "HTTP/1.1 or later" to "HTTP/1.1", in contexts where | ||
9707 | this was incorrectly placing a requirement on the behavior of | ||
9708 | an implementation of a future version of HTTP/1.x | ||
9709 | |||
9710 | 2. Made it clear that user-agents should retry requests, not | ||
9711 | "clients" in general. | ||
9712 | |||
9713 | 3. Converted requirements for clients to ignore unexpected 100 | ||
9714 | (Continue) responses, and for proxies to forward 100 responses, | ||
9715 | into a general requirement for 1xx responses. | ||
9716 | |||
9717 | 4. Modified some TCP-specific language, to make it clearer that | ||
9718 | non-TCP transports are possible for HTTP. | ||
9719 | |||
9720 | 5. Require that the origin server MUST NOT wait for the request | ||
9721 | body before it sends a required 100 (Continue) response. | ||
9722 | |||
9723 | 6. Allow, rather than require, a server to omit 100 (Continue) if | ||
9724 | it has already seen some of the request body. | ||
9725 | |||
9726 | 7. Allow servers to defend against denial-of-service attacks and | ||
9727 | broken clients. | ||
9728 | |||
9729 | This change adds the Expect header and 417 status code. The message | ||
9730 | transmission requirements fixes are in sections 8.2, 10.4.18, | ||
9731 | 8.1.2.2, 13.11, and 14.20. | ||
9732 | |||
9733 | Proxies should be able to add Content-Length when appropriate. | ||
9734 | (Section 13.5.2) | ||
9735 | |||
9736 | Clean up confusion between 403 and 404 responses. (Section 10.4.4, | ||
9737 | 10.4.5, and 10.4.11) | ||
9738 | |||
9739 | Warnings could be cached incorrectly, or not updated appropriately. | ||
9740 | (Section 13.1.2, 13.2.4, 13.5.2, 13.5.3, 14.9.3, and 14.46) Warning | ||
9741 | also needed to be a general header, as PUT or other methods may have | ||
9742 | need for it in requests. | ||
9743 | |||
9744 | |||
9745 | |||
9746 | Fielding, et al. Standards Track [Page 174] | ||
9747 | |||
9748 | RFC 2616 HTTP/1.1 June 1999 | ||
9749 | |||
9750 | |||
9751 | Transfer-coding had significant problems, particularly with | ||
9752 | interactions with chunked encoding. The solution is that transfer- | ||
9753 | codings become as full fledged as content-codings. This involves | ||
9754 | adding an IANA registry for transfer-codings (separate from content | ||
9755 | codings), a new header field (TE) and enabling trailer headers in the | ||
9756 | future. Transfer encoding is a major performance benefit, so it was | ||
9757 | worth fixing [39]. TE also solves another, obscure, downward | ||
9758 | interoperability problem that could have occurred due to interactions | ||
9759 | between authentication trailers, chunked encoding and HTTP/1.0 | ||
9760 | clients.(Section 3.6, 3.6.1, and 14.39) | ||
9761 | |||
9762 | The PATCH, LINK, UNLINK methods were defined but not commonly | ||
9763 | implemented in previous versions of this specification. See RFC 2068 | ||
9764 | [33]. | ||
9765 | |||
9766 | The Alternates, Content-Version, Derived-From, Link, URI, Public and | ||
9767 | Content-Base header fields were defined in previous versions of this | ||
9768 | specification, but not commonly implemented. See RFC 2068 [33]. | ||
9769 | |||
9770 | 20 Index | ||
9771 | |||
9772 | Please see the PostScript version of this RFC for the INDEX. | ||
9773 | |||
9774 | |||
9775 | |||
9776 | |||
9777 | |||
9778 | |||
9779 | |||
9780 | |||
9781 | |||
9782 | |||
9783 | |||
9784 | |||
9785 | |||
9786 | |||
9787 | |||
9788 | |||
9789 | |||
9790 | |||
9791 | |||
9792 | |||
9793 | |||
9794 | |||
9795 | |||
9796 | |||
9797 | |||
9798 | |||
9799 | |||
9800 | |||
9801 | |||
9802 | Fielding, et al. Standards Track [Page 175] | ||
9803 | |||
9804 | RFC 2616 HTTP/1.1 June 1999 | ||
9805 | |||
9806 | |||
9807 | 21. Full Copyright Statement | ||
9808 | |||
9809 | Copyright (C) The Internet Society (1999). All Rights Reserved. | ||
9810 | |||
9811 | This document and translations of it may be copied and furnished to | ||
9812 | others, and derivative works that comment on or otherwise explain it | ||
9813 | or assist in its implementation may be prepared, copied, published | ||
9814 | and distributed, in whole or in part, without restriction of any | ||
9815 | kind, provided that the above copyright notice and this paragraph are | ||
9816 | included on all such copies and derivative works. However, this | ||
9817 | document itself may not be modified in any way, such as by removing | ||
9818 | the copyright notice or references to the Internet Society or other | ||
9819 | Internet organizations, except as needed for the purpose of | ||
9820 | developing Internet standards in which case the procedures for | ||
9821 | copyrights defined in the Internet Standards process must be | ||
9822 | followed, or as required to translate it into languages other than | ||
9823 | English. | ||
9824 | |||
9825 | The limited permissions granted above are perpetual and will not be | ||
9826 | revoked by the Internet Society or its successors or assigns. | ||
9827 | |||
9828 | This document and the information contained herein is provided on an | ||
9829 | "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING | ||
9830 | TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING | ||
9831 | BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION | ||
9832 | HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF | ||
9833 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | ||
9834 | |||
9835 | Acknowledgement | ||
9836 | |||
9837 | Funding for the RFC Editor function is currently provided by the | ||
9838 | Internet Society. | ||
9839 | |||
9840 | |||
9841 | |||
9842 | |||
9843 | |||
9844 | |||
9845 | |||
9846 | |||
9847 | |||
9848 | |||
9849 | |||
9850 | |||
9851 | |||
9852 | |||
9853 | |||
9854 | |||
9855 | |||
9856 | |||
9857 | |||
9858 | Fielding, et al. Standards Track [Page 176] | ||
9859 | |||
diff --git a/src/arraylist.cpp b/src/arraylist.cpp new file mode 100644 index 0000000..ef21426 --- /dev/null +++ b/src/arraylist.cpp | |||
@@ -0,0 +1,100 @@ | |||
1 | #include "arraylist.h" | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | |||
5 | ArrayList::ArrayList( int initSize, int growByFactor ) | ||
6 | { | ||
7 | apData = new void *[initSize]; | ||
8 | nSize = 0; | ||
9 | nCapacity = initSize; | ||
10 | nGrowByFactor = growByFactor; | ||
11 | } | ||
12 | |||
13 | ArrayList::~ArrayList( ) | ||
14 | { | ||
15 | delete[] apData; | ||
16 | } | ||
17 | |||
18 | void *ArrayList::getAt( int index ) | ||
19 | { | ||
20 | if( index < 0 || index > nSize ) | ||
21 | return NULL; | ||
22 | |||
23 | return apData[index]; | ||
24 | } | ||
25 | |||
26 | void ArrayList::append( void *data ) | ||
27 | { | ||
28 | insertBefore( data, nSize ); | ||
29 | } | ||
30 | |||
31 | void ArrayList::insertBefore( void *data, int pos ) | ||
32 | { | ||
33 | if( pos < 0 || pos > nSize ) | ||
34 | return; | ||
35 | |||
36 | checkResize(); | ||
37 | memmove( &apData[pos+1], &apData[pos], (nSize-pos)*sizeof(void*) ); | ||
38 | apData[pos] = data; | ||
39 | nSize++; | ||
40 | } | ||
41 | |||
42 | int ArrayList::getSize( ) | ||
43 | { | ||
44 | return nSize; | ||
45 | } | ||
46 | |||
47 | bool ArrayList::isEmpty( ) | ||
48 | { | ||
49 | return nSize==0; | ||
50 | } | ||
51 | |||
52 | void ArrayList::deleteAt( int index ) | ||
53 | { | ||
54 | if( index < 0 || index >= nSize ) | ||
55 | return; | ||
56 | |||
57 | memmove( &apData[index], &apData[index+1], (nSize-index-1)*sizeof(void *) ); | ||
58 | nSize--; | ||
59 | } | ||
60 | |||
61 | void ArrayList::empty() | ||
62 | { | ||
63 | // Probably the easiest as far as things go. | ||
64 | nSize = 0; | ||
65 | } | ||
66 | |||
67 | void ArrayList::resizeTo( int newSize ) | ||
68 | { | ||
69 | void **apNew = new void *[newSize]; | ||
70 | memmove( apNew, apData, nSize*sizeof(void *) ); | ||
71 | nCapacity = newSize; | ||
72 | delete[] apData; | ||
73 | apData = apNew; | ||
74 | } | ||
75 | |||
76 | void ArrayList::checkResize() | ||
77 | { | ||
78 | if( nSize >= nCapacity ) | ||
79 | { | ||
80 | resizeTo( nCapacity + nGrowByFactor ); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | void ArrayList::setSize( int newSize ) | ||
85 | { | ||
86 | if( newSize < 0 ) | ||
87 | return; | ||
88 | |||
89 | nSize = newSize; | ||
90 | checkResize(); | ||
91 | } | ||
92 | |||
93 | void ArrayList::setAt( int index, void *data ) | ||
94 | { | ||
95 | if( index < 0 || index >= nSize ) | ||
96 | return; | ||
97 | |||
98 | apData[index] = data; | ||
99 | } | ||
100 | |||
diff --git a/src/arraylist.h b/src/arraylist.h new file mode 100644 index 0000000..74992cf --- /dev/null +++ b/src/arraylist.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /** \file arraylist.h | ||
2 | * Describes the ArrayList class. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | #ifndef ARRAY_LIST_H | ||
6 | #define ARRAY_LIST_H | ||
7 | |||
8 | #include "list.h" | ||
9 | |||
10 | /** A simple list which uses an array. This is a great choice if you won't do | ||
11 | * a lot of adding and deleting and need a fast random access list. Otherwise | ||
12 | * use the LinkedList. | ||
13 | *@author Mike Buland | ||
14 | */ | ||
15 | class ArrayList : public List | ||
16 | { | ||
17 | public: | ||
18 | /** Creates an arraylist with some pre-defined specs spelled out. | ||
19 | *@param initSize the inital number of elements to allocate. | ||
20 | *@param growByFactor How much to increase the size of the array by | ||
21 | * each time we run out of room. | ||
22 | */ | ||
23 | ArrayList( int initSize=100, int growByFactor=10 ); | ||
24 | /** | ||
25 | * Destroy the ArrayList | ||
26 | */ | ||
27 | ~ArrayList(); | ||
28 | |||
29 | void *getAt( int nIndex ); | ||
30 | void append( void *pData ); | ||
31 | void insertBefore( void *pData, int nPos = 0 ); | ||
32 | int getSize( ); | ||
33 | bool isEmpty( ); | ||
34 | void deleteAt( int nIndex ); | ||
35 | void empty(); | ||
36 | void setSize( int nNewSize ); | ||
37 | void setAt( int nIndex, void *pData ); | ||
38 | |||
39 | private: | ||
40 | /** | ||
41 | * Checks to see if the system needs to be resized, if it does, this will | ||
42 | * automatically resize based on your parameters. | ||
43 | */ | ||
44 | void checkResize(); | ||
45 | |||
46 | /** | ||
47 | * Resize the system to a specified size. If it is larger, then all data | ||
48 | * will be retained, if smaller the elements at the end will be cut off. | ||
49 | *@param newSize The number of elements to include after resizing. | ||
50 | */ | ||
51 | void resizeTo( int newSize ); | ||
52 | |||
53 | /** | ||
54 | * Actual master array of pointers. This is done to follow the List specs. | ||
55 | * All data transactions are performed with pointers or compatable | ||
56 | * primitive data-types. | ||
57 | */ | ||
58 | void **apData; | ||
59 | |||
60 | /** | ||
61 | * The number of filled in elements in the array. This is the practical | ||
62 | * real size of the ArrayList for all userspace applications. | ||
63 | */ | ||
64 | int nSize; | ||
65 | |||
66 | /** | ||
67 | * The number of elements allocated in memory. Not all of these have to be | ||
68 | * filled in, and it is usually larger than nSize so that adding and | ||
69 | * deleting elements is fast and easy. | ||
70 | */ | ||
71 | int nCapacity; | ||
72 | |||
73 | /** | ||
74 | * The amount to grow by whenever the array needs resizing. | ||
75 | */ | ||
76 | int nGrowByFactor; | ||
77 | }; | ||
78 | |||
79 | #endif | ||
80 | |||
diff --git a/src/cgi.cpp b/src/cgi.cpp new file mode 100644 index 0000000..1fecbbe --- /dev/null +++ b/src/cgi.cpp | |||
@@ -0,0 +1,644 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <stdio.h> | ||
4 | #include <stdarg.h> | ||
5 | #include <sys/stat.h> | ||
6 | |||
7 | #include "cgi.h" | ||
8 | |||
9 | Cgi::Cgi( const char *strSource ) : | ||
10 | aContent( new HashFunctionString(), 151, true ) | ||
11 | { | ||
12 | int length, j, k, mode = 0, slen = 0; | ||
13 | char hexbuf[3] = { 0, 0, 0 }; | ||
14 | char *buf, chr; | ||
15 | Item *cur = NULL; | ||
16 | int nCur = 0; | ||
17 | |||
18 | if( strSource != NULL ) | ||
19 | { | ||
20 | loadContent( strSource ); | ||
21 | } | ||
22 | |||
23 | if( ( getenv( "CONTENT_LENGTH" ) ) ) | ||
24 | { | ||
25 | if( !strcmp | ||
26 | ( getenv( "CONTENT_TYPE" ), | ||
27 | "application/x-www-form-urlencoded" ) ) | ||
28 | { | ||
29 | length = atoi( getenv( "CONTENT_LENGTH" ) ); | ||
30 | buf = new char[length + 1]; | ||
31 | fread( buf, 1, length, stdin ); | ||
32 | cur = new Item( ); | ||
33 | aVars.append( cur ); | ||
34 | cur->type = VAR_STDINPUT; | ||
35 | for( j = 0; j < length; j++ ) | ||
36 | { | ||
37 | switch ( buf[j] ) | ||
38 | { | ||
39 | case '=': | ||
40 | cur->name = new char[slen + 1]; | ||
41 | slen = 0; | ||
42 | break; | ||
43 | |||
44 | case '&': | ||
45 | cur->value = new char[slen + 1]; | ||
46 | cur->len = slen; | ||
47 | slen = 0; | ||
48 | cur = new Item( ); | ||
49 | aVars.append( cur ); | ||
50 | cur->type = VAR_STDINPUT; | ||
51 | break; | ||
52 | |||
53 | default: | ||
54 | switch ( buf[j] ) | ||
55 | { | ||
56 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
57 | j += 2; | ||
58 | slen++; | ||
59 | break; | ||
60 | |||
61 | default: /* Nothing special, move along, folks... */ | ||
62 | slen++; | ||
63 | break; | ||
64 | } | ||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | cur->value = new char[slen + 1]; | ||
69 | cur->len = slen; | ||
70 | slen = 0; | ||
71 | mode = 0; | ||
72 | cur = ( Item * ) aVars.getAt( 0 ); | ||
73 | k = 0; | ||
74 | nCur = 0; | ||
75 | for( j = 0; j < length; j++ ) | ||
76 | { | ||
77 | switch ( buf[j] ) | ||
78 | { | ||
79 | case '=': | ||
80 | mode = 1; | ||
81 | k = 0; | ||
82 | break; | ||
83 | |||
84 | case '&': | ||
85 | mode = 0; | ||
86 | k = 0; | ||
87 | nCur++; | ||
88 | cur = ( Item * ) aVars.getAt( nCur ); | ||
89 | break; | ||
90 | |||
91 | default: | ||
92 | switch ( buf[j] ) | ||
93 | { | ||
94 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
95 | hexbuf[0] = buf[++j]; | ||
96 | hexbuf[1] = buf[++j]; | ||
97 | chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); | ||
98 | break; | ||
99 | |||
100 | case '+': /* Pluses mean spaces, odd, I know... */ | ||
101 | chr = ' '; | ||
102 | break; | ||
103 | |||
104 | default: /* Nothing special, move along, folks... */ | ||
105 | chr = buf[j]; | ||
106 | break; | ||
107 | } | ||
108 | if( mode == 0 ) | ||
109 | { | ||
110 | cur->name[k] = chr; | ||
111 | cur->name[++k] = '\0'; | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | cur->value[k] = chr; | ||
116 | cur->value[++k] = '\0'; | ||
117 | } | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | delete buf; | ||
122 | } | ||
123 | else if( !strncmp | ||
124 | ( getenv( "CONTENT_TYPE" ), "multipart/form-data;", 20 ) ) | ||
125 | { | ||
126 | char *boundary, *oname; | ||
127 | int blen, j, k, olen; | ||
128 | |||
129 | length = atoi( getenv( "CONTENT_LENGTH" ) ); | ||
130 | buf = new char[length + 1]; | ||
131 | fread( buf, 1, length, stdin ); | ||
132 | for( blen = 0; buf[blen + 1] != '\n'; blen++ ); | ||
133 | boundary = new char[blen + 1]; | ||
134 | memcpy( boundary, buf, blen ); | ||
135 | boundary[blen] = '\0'; | ||
136 | j = blen + 2; | ||
137 | for( ;; ) | ||
138 | { | ||
139 | cur = new Item( ); | ||
140 | aVars.append( cur ); | ||
141 | cur->type = VAR_STDINPUT; | ||
142 | if( !strncmp | ||
143 | ( buf + j, "Content-Disposition: form-data; name=\"", | ||
144 | 38 ) ) | ||
145 | { | ||
146 | j += 38; | ||
147 | for( k = 0; buf[j + k] != '\"'; k++ ); | ||
148 | oname = cur->name = new char[k + 1]; | ||
149 | memcpy( cur->name, buf + j, k ); | ||
150 | olen = k; | ||
151 | cur->name[k] = '\0'; | ||
152 | j += k + 1; | ||
153 | if( !strncmp( buf + j, "; filename=\"", 12 ) ) /* Must be a file */ | ||
154 | { | ||
155 | /* Acquire file name */ | ||
156 | j += 12; | ||
157 | for( k = 0; buf[j + k] != '\"'; k++ ); | ||
158 | cur->value = new char[k + 1]; | ||
159 | memcpy( cur->value, buf + j, k ); | ||
160 | cur->value[k] = '\0'; | ||
161 | cur->len = k; | ||
162 | j += k + 3; | ||
163 | |||
164 | /* Acquire content type */ | ||
165 | if( !strncmp( "Content-Type: ", buf + j, 14 ) ) | ||
166 | { | ||
167 | j += 14; | ||
168 | cur = new Item( ); | ||
169 | aVars.append( cur ); | ||
170 | cur->type = VAR_STDINPUT; | ||
171 | cur->name = new char[olen + 1]; | ||
172 | memcpy( cur->name, oname, olen + 1 ); | ||
173 | for( k = 0; buf[j + k + 1] != '\n'; k++ ); | ||
174 | cur->value = new char[k + 1]; | ||
175 | memcpy( cur->value, buf + j, k ); | ||
176 | cur->value[k] = '\0'; | ||
177 | cur->len = k; | ||
178 | j += k; | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | cur = new Item( ); | ||
183 | aVars.append( cur ); | ||
184 | cur->type = VAR_STDINPUT; | ||
185 | cur->name = new char[olen + 1]; | ||
186 | memcpy( cur->name, oname, olen + 1 ); | ||
187 | cur->value = new char[1]; | ||
188 | cur->value[0] = '\0'; | ||
189 | cur->len = 0; | ||
190 | } | ||
191 | j += 4; | ||
192 | |||
193 | /* Acquire content */ | ||
194 | cur = new Item( ); | ||
195 | aVars.append( cur ); | ||
196 | cur->type = VAR_STDINPUT; | ||
197 | cur->name = new char[olen + 1]; | ||
198 | memcpy( cur->name, oname, olen + 1 ); | ||
199 | if( !strncmp( buf + j + k, boundary, blen ) ) | ||
200 | { | ||
201 | cur->value = new char[1]; | ||
202 | cur->value[0] = '\0'; | ||
203 | j += blen + 4; | ||
204 | } | ||
205 | else if( !strncmp( buf + j + k + 1, boundary, blen ) ) | ||
206 | { | ||
207 | cur->value = new char[1]; | ||
208 | cur->value[0] = '\0'; | ||
209 | j += blen + 5; | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | for( k = 0; | ||
214 | strncmp( buf + j + k + 2, boundary, blen ); | ||
215 | k++ ); | ||
216 | cur->value = new char[k + 1]; | ||
217 | memcpy( cur->value, buf + j, k ); | ||
218 | cur->value[k] = '\0'; | ||
219 | cur->len = k; | ||
220 | j += k + blen + 4; | ||
221 | } | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | j += 4; | ||
226 | for( k = 0; | ||
227 | strncmp( buf + j + k + 2, boundary, blen ); | ||
228 | k++ ); | ||
229 | cur->value = new char[k + 1]; | ||
230 | memcpy( cur->value, buf + j, k ); | ||
231 | cur->value[k] = '\0'; | ||
232 | cur->len = k; | ||
233 | j += k + blen + 4; | ||
234 | } | ||
235 | if( buf[j + 1] == '\n' ) | ||
236 | j += 2; | ||
237 | if( j >= length ) | ||
238 | break; | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | cur->name = ( char * ) "ERROR"; | ||
243 | cur->value = ( char * ) "Error here"; | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | delete buf; | ||
248 | } | ||
249 | |||
250 | if( ( buf = getenv( "HTTP_COOKIE" ) ) ) | ||
251 | { | ||
252 | int lbase = aVars.getSize( ); | ||
253 | length = strlen( buf ); | ||
254 | cur = new Item( ); | ||
255 | aVars.append( cur ); | ||
256 | cur->type = VAR_COOKIE; | ||
257 | for( j = 0; j < length; j++ ) | ||
258 | { | ||
259 | switch ( buf[j] ) | ||
260 | { | ||
261 | case '=': | ||
262 | cur->name = new char[slen + 1]; | ||
263 | slen = 0; | ||
264 | break; | ||
265 | |||
266 | case ';': | ||
267 | cur->value = new char[slen + 1]; | ||
268 | cur->len = slen; | ||
269 | slen = 0; | ||
270 | cur = new Item( ); | ||
271 | aVars.append( cur ); | ||
272 | cur->type = VAR_COOKIE; | ||
273 | break; | ||
274 | |||
275 | default: | ||
276 | switch ( buf[j] ) | ||
277 | { | ||
278 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
279 | j += 2; | ||
280 | slen++; | ||
281 | break; | ||
282 | |||
283 | default: /* Nothing special, move along, folks... */ | ||
284 | slen++; | ||
285 | break; | ||
286 | } | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | cur->value = new char[slen + 1]; | ||
291 | cur->len = slen; | ||
292 | slen = 0; | ||
293 | cur = ( Item * ) aVars.getAt( lbase ); | ||
294 | mode = 0; | ||
295 | k = 0; | ||
296 | nCur = lbase; | ||
297 | for( j = 0; j < length; j++ ) | ||
298 | { | ||
299 | switch ( buf[j] ) | ||
300 | { | ||
301 | case '=': | ||
302 | mode = 1; | ||
303 | k = 0; | ||
304 | break; | ||
305 | |||
306 | case ';': | ||
307 | mode = 0; | ||
308 | k = 0; | ||
309 | nCur++; | ||
310 | cur = ( Item * ) aVars.getAt( nCur ); | ||
311 | break; | ||
312 | |||
313 | default: | ||
314 | switch ( buf[j] ) | ||
315 | { | ||
316 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
317 | hexbuf[0] = buf[++j]; | ||
318 | hexbuf[1] = buf[++j]; | ||
319 | chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); | ||
320 | break; | ||
321 | |||
322 | case '+': /* Pluses mean spaces, odd, I know... */ | ||
323 | chr = ' '; | ||
324 | break; | ||
325 | |||
326 | case ' ': | ||
327 | continue; | ||
328 | break; | ||
329 | |||
330 | default: /* Nothing special, move along, folks... */ | ||
331 | chr = buf[j]; | ||
332 | break; | ||
333 | } | ||
334 | if( mode == 0 ) | ||
335 | { | ||
336 | cur->name[k] = chr; | ||
337 | cur->name[++k] = '\0'; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | cur->value[k] = chr; | ||
342 | cur->value[++k] = '\0'; | ||
343 | } | ||
344 | break; | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | |||
349 | if( ( buf = getenv( "QUERY_STRING" ) ) ) | ||
350 | { | ||
351 | if( strlen( buf ) > 0 ) | ||
352 | { | ||
353 | int lbase = aVars.getSize( ); | ||
354 | length = strlen( buf ); | ||
355 | cur = new Item( ); | ||
356 | aVars.append( cur ); | ||
357 | cur->type = VAR_CMDLINE; | ||
358 | for( j = 0; j < length; j++ ) | ||
359 | { | ||
360 | switch ( buf[j] ) | ||
361 | { | ||
362 | case '=': | ||
363 | cur->name = new char[slen + 1]; | ||
364 | slen = 0; | ||
365 | break; | ||
366 | |||
367 | case '&': | ||
368 | cur->value = new char[slen + 1]; | ||
369 | cur->len = slen; | ||
370 | slen = 0; | ||
371 | cur = new Item( ); | ||
372 | aVars.append( cur ); | ||
373 | cur->type = VAR_CMDLINE; | ||
374 | break; | ||
375 | |||
376 | default: | ||
377 | switch ( buf[j] ) | ||
378 | { | ||
379 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
380 | j += 2; | ||
381 | slen++; | ||
382 | break; | ||
383 | |||
384 | default: /* Nothing special, move along, folks... */ | ||
385 | slen++; | ||
386 | break; | ||
387 | } | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | cur->value = new char[slen + 1]; | ||
392 | cur->len = slen; | ||
393 | slen = 0; | ||
394 | cur = ( Item * ) aVars.getAt( lbase ); | ||
395 | nCur = lbase; | ||
396 | mode = 0; | ||
397 | k = 0; | ||
398 | for( j = 0; j < length; j++ ) | ||
399 | { | ||
400 | switch ( buf[j] ) | ||
401 | { | ||
402 | case '=': | ||
403 | mode = 1; | ||
404 | k = 0; | ||
405 | break; | ||
406 | |||
407 | case '&': | ||
408 | mode = 0; | ||
409 | k = 0; | ||
410 | nCur++; | ||
411 | cur = ( Item * ) aVars.getAt( nCur ); | ||
412 | break; | ||
413 | |||
414 | default: | ||
415 | switch ( buf[j] ) | ||
416 | { | ||
417 | case '%': /* per-cents mean a hex-code for an ASCII char */ | ||
418 | hexbuf[0] = buf[++j]; | ||
419 | hexbuf[1] = buf[++j]; | ||
420 | chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); | ||
421 | break; | ||
422 | |||
423 | case '+': /* Pluses mean spaces, odd, I know... */ | ||
424 | chr = ' '; | ||
425 | break; | ||
426 | |||
427 | default: /* Nothing special, move along, folks... */ | ||
428 | chr = buf[j]; | ||
429 | break; | ||
430 | } | ||
431 | if( mode == 0 ) | ||
432 | { | ||
433 | cur->name[k] = chr; | ||
434 | cur->name[++k] = '\0'; | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | cur->value[k] = chr; | ||
439 | cur->value[++k] = '\0'; | ||
440 | } | ||
441 | break; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | |||
448 | Cgi::~Cgi( ) | ||
449 | { | ||
450 | } | ||
451 | |||
452 | char *Cgi::getVarValue( const char *name, int skip, unsigned char type ) | ||
453 | { | ||
454 | for( int j = 0; j < aVars.getSize( ); j++ ) | ||
455 | { | ||
456 | Item *cur = ( Item * ) aVars.getAt( j ); | ||
457 | if( !strcmp( cur->name, name ) ) | ||
458 | { | ||
459 | if( ( cur->type & type ) ) | ||
460 | { | ||
461 | if( skip <= 0 ) | ||
462 | { | ||
463 | return cur->value; | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | skip--; | ||
468 | } | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | return NULL; | ||
473 | } | ||
474 | |||
475 | int Cgi::getVarLength( const char *name, int skip, unsigned char type ) | ||
476 | { | ||
477 | for( int j = 0; j < aVars.getSize( ); j++ ) | ||
478 | { | ||
479 | Item *cur = ( Item * ) aVars.getAt( j ); | ||
480 | if( !strcmp( cur->name, name ) ) | ||
481 | { | ||
482 | if( ( cur->type & type ) ) | ||
483 | { | ||
484 | if( skip <= 0 ) | ||
485 | { | ||
486 | return cur->len; | ||
487 | } | ||
488 | else | ||
489 | { | ||
490 | skip--; | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | } | ||
495 | return -1; | ||
496 | } | ||
497 | |||
498 | void Cgi::writeDebugInfo() | ||
499 | { | ||
500 | printf( "<pre>\n" ); | ||
501 | printf( "0x%02X - stdInput | 0x%02X - cookie | 0x%02X - cmdLine\n\n", | ||
502 | VAR_STDINPUT, VAR_COOKIE, VAR_CMDLINE ); | ||
503 | for( int j = 0; j < aVars.getSize( ); j++ ) | ||
504 | { | ||
505 | Item *item = ( Item * ) aVars.getAt( j ); | ||
506 | printf("[%s] = \"%s\" [0x%02X]\n", item->name, | ||
507 | item->value, item->type ); | ||
508 | } | ||
509 | printf( "</pre>\n" ); | ||
510 | } | ||
511 | |||
512 | void Cgi::writeContentHeader( int type ) | ||
513 | { | ||
514 | switch( type ) | ||
515 | { | ||
516 | case headerHTML: | ||
517 | printf("Content-type: text/html\n\n"); | ||
518 | break; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | void Cgi::writeContent( const char *name, ...) | ||
523 | { | ||
524 | char *templ = (char *)aContent.get(name); | ||
525 | |||
526 | if( templ ) | ||
527 | { | ||
528 | va_list ap; | ||
529 | |||
530 | va_start (ap, name); | ||
531 | vprintf (templ, ap); | ||
532 | va_end (ap); | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | printf("Error finding content labeled \"%s\"\n", name ); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | void Cgi::loadContent( const char *strSource ) | ||
541 | { | ||
542 | FILE *fh = NULL; | ||
543 | if( strSource == NULL ) | ||
544 | { | ||
545 | extern char *program_invocation_short_name; | ||
546 | char *tmpName = new char[strlen(program_invocation_short_name)+10]; | ||
547 | memset( tmpName, 0, strlen(program_invocation_short_name)+10 ); | ||
548 | strcpy( tmpName, program_invocation_short_name ); | ||
549 | strcat( tmpName, ".content" ); | ||
550 | fh = fopen( tmpName, "rt" ); | ||
551 | delete tmpName; | ||
552 | } | ||
553 | else | ||
554 | { | ||
555 | fh = fopen( strSource, "rt" ); | ||
556 | } | ||
557 | |||
558 | if( fh == NULL ) return; | ||
559 | |||
560 | struct stat xStats; | ||
561 | |||
562 | fstat( fileno( fh ), &xStats ); | ||
563 | |||
564 | char *bigBuf = new char[xStats.st_size+1]; | ||
565 | memset( bigBuf, 0, xStats.st_size+1 ); | ||
566 | fread( bigBuf, 1, xStats.st_size, fh ); | ||
567 | fclose( fh ); | ||
568 | |||
569 | // Now we can actually load stuff from the file, first we need to make us up a format... | ||
570 | int lSize=0; | ||
571 | struct Content | ||
572 | { | ||
573 | char *name; | ||
574 | char *value; | ||
575 | } xCont; | ||
576 | int j = 0; | ||
577 | while( j < xStats.st_size ) | ||
578 | { | ||
579 | // We're looking for a content-block init statement | ||
580 | for( ; j < xStats.st_size; j++ ) | ||
581 | { | ||
582 | if( bigBuf[j] == '#' ) | ||
583 | { | ||
584 | if( bigBuf[j+1] == '{' ) | ||
585 | { | ||
586 | break; | ||
587 | } | ||
588 | } | ||
589 | } | ||
590 | j=j+2; | ||
591 | if( j >= xStats.st_size ) break; | ||
592 | for( ; bigBuf[j] == ' ' || bigBuf[j] == '\t'; j++ ); | ||
593 | for( lSize = 0; lSize+j < xStats.st_size && bigBuf[lSize+j] != '\n' && bigBuf[lSize+j] != '\r'; lSize++ ); | ||
594 | xCont.name = new char[lSize+1]; | ||
595 | memset( xCont.name, 0, lSize+1 ); | ||
596 | memcpy( xCont.name, &bigBuf[j], lSize ); | ||
597 | j += lSize+1; | ||
598 | |||
599 | for( lSize = 0; lSize+j < xStats.st_size; lSize++ ) | ||
600 | { | ||
601 | if( bigBuf[lSize+j] == '#' ) | ||
602 | { | ||
603 | if( bigBuf[lSize+j+1] == '}' ) | ||
604 | { | ||
605 | break; | ||
606 | } | ||
607 | } | ||
608 | } | ||
609 | xCont.value = new char[lSize+1]; | ||
610 | memset( xCont.value, 0, lSize+1 ); | ||
611 | memcpy( xCont.value, &bigBuf[j], lSize ); | ||
612 | |||
613 | aContent.insert( xCont.name, xCont.value ); | ||
614 | |||
615 | j += lSize + 2; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | void Cgi::writeCookie( char const *name, char const *value, char const *expires, char const *path, char const *domain, bool secure ) | ||
620 | { | ||
621 | printf("Set-Cookie: %s=%s", name, value ); | ||
622 | |||
623 | if( expires != NULL ) | ||
624 | { | ||
625 | printf("; expires=%s", expires ); | ||
626 | } | ||
627 | |||
628 | if( path != NULL ) | ||
629 | { | ||
630 | printf("; path=%s", path ); | ||
631 | } | ||
632 | |||
633 | if( domain != NULL ) | ||
634 | { | ||
635 | printf("; domain=%s", domain ); | ||
636 | } | ||
637 | |||
638 | if( secure ) | ||
639 | { | ||
640 | printf("; secure"); | ||
641 | } | ||
642 | |||
643 | printf("\n"); | ||
644 | } | ||
diff --git a/src/cgi.h b/src/cgi.h new file mode 100644 index 0000000..8e9a584 --- /dev/null +++ b/src/cgi.h | |||
@@ -0,0 +1,196 @@ | |||
1 | /**\file cgi.h | ||
2 | * Describes extra params needed to use the Cgi class as well as the class | ||
3 | * itself. | ||
4 | *@author Mike Buland | ||
5 | */ | ||
6 | |||
7 | #include "linkedlist.h" | ||
8 | #include "hashtable.h" | ||
9 | #include "hashfunctionstring.h" | ||
10 | |||
11 | #define VAR_STDINPUT 0x01 /**< Variable came from stdinput, web form */ | ||
12 | #define VAR_COOKIE 0x02 /**< Variable came from a cookie */ | ||
13 | #define VAR_CMDLINE 0x04 /**< Variable came from commandline / uri */ | ||
14 | #define VAR_ANY 0xFF /**< Mask including all other types */ | ||
15 | |||
16 | /** | ||
17 | * Cgi header processor originally designed for apache cgi programs. When used | ||
18 | * from apache with what I beleive are some sort of standard set of command | ||
19 | * line parameters and environment variables. This always worked for all of my | ||
20 | * purposes. This class will automatically extract all data from the system | ||
21 | * that you need and places it into tables and things for easy access. | ||
22 | * There are three types of input that data can come from, StandardInput, | ||
23 | * CommandLine, and Cookies. StandardInput is when you get formdata in | ||
24 | * multi-part forms, Cookies should usually be cookies that you set, and | ||
25 | * command line is everything after the question mark in the URL. | ||
26 | * This also contains some simple helpers for putting templated data into the | ||
27 | * HTTP data feed. | ||
28 | *@author Mike Buland | ||
29 | */ | ||
30 | class Cgi | ||
31 | { | ||
32 | public: | ||
33 | /** | ||
34 | * Create a complete CGI object, this object will automatically read data | ||
35 | * from all available sources and be ready for use on the very next line! | ||
36 | * If strSource is filled in it will also automatically read in a content | ||
37 | * file, which is a simple file format containing named blocks of reusable | ||
38 | * templates. | ||
39 | *@param strSource Set to a filename in order to load up a content file. | ||
40 | */ | ||
41 | Cgi( const char *strSource = NULL ); | ||
42 | |||
43 | /** | ||
44 | * Destroy the cgi object. | ||
45 | */ | ||
46 | ~Cgi( ); | ||
47 | |||
48 | /** | ||
49 | * Get's the value for a variable as a character string. The name is the | ||
50 | * name that was given on the URL or in the form or cookie. Skip can be | ||
51 | * set to any value above zero to retreive subsequent variables with the | ||
52 | * same name. The most obvious use of this is when dealing with file | ||
53 | * uploads, each file upload sends you three variables with the same name | ||
54 | * and different content. Finally the variable type determines where you | ||
55 | * will accept this variable from. This is generally a bit of a security | ||
56 | * thing, if you store login info in a cookie and don't want people getting | ||
57 | * in by faking the appropriate URL. | ||
58 | *@param name The name of the variable you wish to retreive. | ||
59 | *@param skip THe number of variables with the given name to skip before | ||
60 | * returning something meaningful. The only way to determine how many | ||
61 | * variables with the same name there are is to skip until you get a NULL | ||
62 | * value returned. | ||
63 | *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, | ||
64 | * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the | ||
65 | * values together. If a variable is found but came from the wrong source | ||
66 | * it won't match any other criteria and will be treated as though it | ||
67 | * doesn't exist. | ||
68 | *@returns A null-terminated string representing the value of the requested | ||
69 | * variable, or NULL if the variable did not exist. If a variable does | ||
70 | * exist but has no value the string returned will start with a NULL char, | ||
71 | * but be a valid string. | ||
72 | */ | ||
73 | char *getVarValue( const char *name, int skip=0, unsigned char type=VAR_ANY ); | ||
74 | |||
75 | /** | ||
76 | * This functions identically in every way to getVarValue, except that | ||
77 | * instead of returning a pointer to the variable's value, it returns the | ||
78 | * length of the variable's value string. The params are the same and so | ||
79 | * a call to both functions with the same params should yeild a value and | ||
80 | * a corresponding length. | ||
81 | *@param name The name of the variable you wish to retreive. | ||
82 | *@param skip THe number of variables with the given name to skip before | ||
83 | * returning something meaningful. The only way to determine how many | ||
84 | * variables with the same name there are is to skip until you get a NULL | ||
85 | * value returned. | ||
86 | *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, | ||
87 | * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the | ||
88 | * values together. If a variable is found but came from the wrong source | ||
89 | * it won't match any other criteria and will be treated as though it | ||
90 | * doesn't exist. | ||
91 | *@returns The length of the value-string of the requested variable. If | ||
92 | * the requested variable is not found, -1 is returned. | ||
93 | */ | ||
94 | int getVarLength( const char *name, int skip=0, unsigned char type=VAR_ANY ); | ||
95 | |||
96 | /** | ||
97 | * A handy little function that writes a load of debug info related to | ||
98 | * parsing CGI params to the standard output in html. This is generally | ||
99 | * best used at the end of a page. | ||
100 | */ | ||
101 | void writeDebugInfo(); | ||
102 | |||
103 | /** | ||
104 | * Write a content header to the standard output. This should also be the | ||
105 | * first thing that you do (except for writing cookies) after initializing | ||
106 | * the Cgi class. You can select a type of header or content from the | ||
107 | * header enum, and a properly formatted header will show up on the | ||
108 | * standard output. | ||
109 | *@param type Any value from the header enum in this class. The default is | ||
110 | * to write an html header, probably the most common as well. | ||
111 | */ | ||
112 | void writeContentHeader( int type=headerHTML ); | ||
113 | |||
114 | /** | ||
115 | * Write content to the stnadard output. The content variable should have | ||
116 | * been loaded during construction of the Cgi object or with the | ||
117 | * loadContent function. The content variable should be formatted just like | ||
118 | * a printf string, so that anything you want to put into it will have a % | ||
119 | * symbol replacement code, like %s, %d, etc. Since this actually uses a | ||
120 | * type of printf function everything from those docs work here. | ||
121 | *@param name The name of the content variable to format and write to | ||
122 | * stnadard output. | ||
123 | *@param ... As many params as you want to include, ala printf. | ||
124 | */ | ||
125 | void writeContent( const char *name, ...); | ||
126 | |||
127 | /** | ||
128 | * Load a content file. I don't want to describe the format here, you can | ||
129 | * just read the code or find an example for now. Sorry. | ||
130 | *@param strSource The name of the file to open and read in to get the | ||
131 | * content loaded. | ||
132 | */ | ||
133 | void loadContent( const char *strSource = NULL ); | ||
134 | |||
135 | /** | ||
136 | * Write a cookie-set header to the output stream. This should be done | ||
137 | * before any other content-headers are written. The specifics of this | ||
138 | * function are very simple, since I rely on the user's understanding of | ||
139 | * how standard HTTP/1.1 or HTTP/1.0 cookie syntax works. If you don't | ||
140 | * care then just use the name and value and the defaults should keep you | ||
141 | * in good stead for a long time. | ||
142 | *@param name The name of the cookie variable to set. | ||
143 | *@param value The value to set to that variable. | ||
144 | *@param expires The formatted string value for the date and time this | ||
145 | * cookie should expire. A NULL here will put a "until the browser closes" | ||
146 | * tag in. | ||
147 | *@param path The path (URL) that this cookie belongs to. If you run a lot | ||
148 | * of hosted servers or sub-sites that may have some shared URL bits then | ||
149 | * you may want to set this. The cookie should only be sent to URL's that | ||
150 | * match this as their first part. | ||
151 | *@param domain The domain that is allowed to read this, if not set, it's | ||
152 | * the domain the web browser contacted when they got the cookie. | ||
153 | *@param secure I'm not sure, I think it's something to tell if the cookie | ||
154 | * is safe to keep because any potentially valuable data is encypted or | ||
155 | * otherwise unusable. I could be wrong. | ||
156 | */ | ||
157 | void writeCookie( char const *name, char const *value, char const *expires=NULL, char const *path=NULL, char const *domain=NULL, bool secure=false ); | ||
158 | |||
159 | /** | ||
160 | * A simple helper class to contain variable data. | ||
161 | */ | ||
162 | class Item | ||
163 | { | ||
164 | public: | ||
165 | /** | ||
166 | * Build an empty Item. | ||
167 | */ | ||
168 | Item( ) | ||
169 | { | ||
170 | name = NULL; | ||
171 | value = NULL; | ||
172 | len = 0; | ||
173 | type = 0; | ||
174 | } | ||
175 | /** The name of the item. */ | ||
176 | char *name; | ||
177 | /** The value of the item. */ | ||
178 | char *value; | ||
179 | /** The length of the item's value. */ | ||
180 | unsigned long len; | ||
181 | /** The type of the item (where it came from). */ | ||
182 | unsigned char type; | ||
183 | }; | ||
184 | |||
185 | /** Header values */ | ||
186 | enum | ||
187 | { | ||
188 | headerHTML | ||
189 | }; | ||
190 | |||
191 | private: | ||
192 | /** Keeps track of all contained variables. */ | ||
193 | LinkedList aVars; | ||
194 | /** Keeps track of all content variables. */ | ||
195 | HashTable aContent; | ||
196 | }; | ||
diff --git a/src/connection.cpp b/src/connection.cpp new file mode 100644 index 0000000..a277ea7 --- /dev/null +++ b/src/connection.cpp | |||
@@ -0,0 +1,432 @@ | |||
1 | #include "connection.h" | ||
2 | #include <string.h> | ||
3 | #include <stdio.h> | ||
4 | #include <errno.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <unistd.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <sys/socket.h> | ||
9 | #include <netinet/in.h> | ||
10 | #include <netdb.h> | ||
11 | #include <arpa/inet.h> | ||
12 | |||
13 | Connection::Connection() | ||
14 | { | ||
15 | nSocket = -1; | ||
16 | bActive = false; | ||
17 | bDisconnectMe = false; | ||
18 | pProtocol = NULL; | ||
19 | } | ||
20 | |||
21 | Connection::~Connection() | ||
22 | { | ||
23 | if( pProtocol != NULL ) delete pProtocol; | ||
24 | } | ||
25 | |||
26 | bool Connection::appendOutput( const char *lpOutput, int nSize ) | ||
27 | { | ||
28 | return xOutputBuf.appendData( lpOutput, nSize ); | ||
29 | } | ||
30 | |||
31 | bool Connection::appendOutput( const char lOutput ) | ||
32 | { | ||
33 | return xOutputBuf.appendData( lOutput ); | ||
34 | } | ||
35 | |||
36 | bool Connection::appendOutput( const short lOutput ) | ||
37 | { | ||
38 | return xOutputBuf.appendData( lOutput ); | ||
39 | } | ||
40 | |||
41 | bool Connection::appendOutput( const int lOutput ) | ||
42 | { | ||
43 | return xOutputBuf.appendData( lOutput ); | ||
44 | } | ||
45 | |||
46 | bool Connection::appendOutput( const long lOutput ) | ||
47 | { | ||
48 | return xOutputBuf.appendData( lOutput ); | ||
49 | } | ||
50 | |||
51 | bool Connection::appendOutput( const float lOutput ) | ||
52 | { | ||
53 | return xOutputBuf.appendData( lOutput ); | ||
54 | } | ||
55 | |||
56 | bool Connection::appendOutput( const double lOutput ) | ||
57 | { | ||
58 | return xOutputBuf.appendData( lOutput ); | ||
59 | } | ||
60 | |||
61 | bool Connection::appendOutput( const unsigned char lOutput ) | ||
62 | { | ||
63 | return xOutputBuf.appendData( lOutput ); | ||
64 | } | ||
65 | |||
66 | bool Connection::appendOutput( const unsigned short lOutput ) | ||
67 | { | ||
68 | return xOutputBuf.appendData( lOutput ); | ||
69 | } | ||
70 | |||
71 | bool Connection::appendOutput( const unsigned long lOutput ) | ||
72 | { | ||
73 | return xOutputBuf.appendData( lOutput ); | ||
74 | } | ||
75 | |||
76 | bool Connection::appendOutput( const unsigned int lOutput ) | ||
77 | { | ||
78 | return xOutputBuf.appendData( lOutput ); | ||
79 | } | ||
80 | |||
81 | bool Connection::appendInput( const char *lpInput, int nSize ) | ||
82 | { | ||
83 | return xInputBuf.appendData( lpInput, nSize ); | ||
84 | } | ||
85 | |||
86 | int Connection::scanInputFor( char cTarget ) | ||
87 | { | ||
88 | const char *lpTmp = xInputBuf.getData(); | ||
89 | int jMax = xInputBuf.getLength(); | ||
90 | |||
91 | for( int j = 0; j < jMax; j++ ) | ||
92 | { | ||
93 | if( lpTmp[j] == cTarget ) | ||
94 | { | ||
95 | return j; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | return -1; | ||
100 | } | ||
101 | |||
102 | const char *Connection::getOutput() | ||
103 | { | ||
104 | return xOutputBuf.getData(); | ||
105 | } | ||
106 | |||
107 | const char *Connection::getInput() | ||
108 | { | ||
109 | return xInputBuf.getData(); | ||
110 | } | ||
111 | |||
112 | void Connection::setSocket( int nNewSocket ) | ||
113 | { | ||
114 | nSocket = nNewSocket; | ||
115 | } | ||
116 | |||
117 | int Connection::getSocket() | ||
118 | { | ||
119 | return nSocket; | ||
120 | } | ||
121 | |||
122 | bool Connection::isActive() | ||
123 | { | ||
124 | return bActive; | ||
125 | } | ||
126 | |||
127 | void Connection::close() | ||
128 | { | ||
129 | if( bActive ) | ||
130 | { | ||
131 | fsync( nSocket ); | ||
132 | ::close( nSocket ); | ||
133 | } | ||
134 | bActive = false; | ||
135 | //nSocket = -1; | ||
136 | xInputBuf.clearData(); | ||
137 | xOutputBuf.clearData(); | ||
138 | if( pProtocol != NULL ) | ||
139 | { | ||
140 | delete pProtocol; | ||
141 | pProtocol = NULL; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | bool Connection::open( int nNewSocket ) | ||
146 | { | ||
147 | bActive = true; | ||
148 | setSocket( nNewSocket ); | ||
149 | bDisconnectMe = false; | ||
150 | |||
151 | return true; | ||
152 | } | ||
153 | |||
154 | bool Connection::open( const char *sAddr, int nPort ) | ||
155 | { | ||
156 | struct sockaddr_in xServerName; | ||
157 | bActive = false; | ||
158 | |||
159 | /* Create the socket. */ | ||
160 | nSocket = socket( PF_INET, SOCK_STREAM, 0 ); | ||
161 | if( nSocket < 0 ) | ||
162 | { | ||
163 | bActive = false; | ||
164 | return false; | ||
165 | } | ||
166 | |||
167 | /* Connect to the server. */ | ||
168 | { | ||
169 | struct hostent *hostinfo; | ||
170 | |||
171 | xServerName.sin_family = AF_INET; | ||
172 | xServerName.sin_port = htons( nPort ); | ||
173 | hostinfo = gethostbyname( sAddr ); | ||
174 | if (hostinfo == NULL) | ||
175 | { | ||
176 | return false; | ||
177 | } | ||
178 | xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr; | ||
179 | } | ||
180 | |||
181 | int ret = connect( | ||
182 | nSocket, | ||
183 | (struct sockaddr *)&xServerName, | ||
184 | sizeof(xServerName) | ||
185 | ); | ||
186 | |||
187 | if( ret < 0 ) | ||
188 | { | ||
189 | return false; | ||
190 | } | ||
191 | |||
192 | bActive = true; | ||
193 | bDisconnectMe = false; | ||
194 | |||
195 | return true; | ||
196 | } | ||
197 | |||
198 | bool Connection::readInput() | ||
199 | { | ||
200 | char buffer[2048]; | ||
201 | int nbytes; | ||
202 | int nTotalRead=0; | ||
203 | |||
204 | for(;;) | ||
205 | { | ||
206 | memset( buffer, 0, 2048 ); | ||
207 | |||
208 | nbytes = read( nSocket, buffer, 2048 ); | ||
209 | if (nbytes < 0) | ||
210 | { | ||
211 | /* Read error. */ | ||
212 | //perror("readInput"); | ||
213 | return false; | ||
214 | } | ||
215 | else if (nbytes == 0) | ||
216 | { | ||
217 | /* End-of-file. */ | ||
218 | //perror("readInput"); | ||
219 | return false; | ||
220 | } | ||
221 | else | ||
222 | { | ||
223 | nTotalRead += nbytes; | ||
224 | appendInput( buffer, nbytes ); | ||
225 | /* Data read. */ | ||
226 | if( nbytes < 2047 ) | ||
227 | { | ||
228 | if( pProtocol != NULL && nTotalRead > 0 ) | ||
229 | { | ||
230 | pProtocol->onNewData(); | ||
231 | } | ||
232 | |||
233 | return true; | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | return true; | ||
239 | } | ||
240 | |||
241 | bool Connection::readInput( int nSec, int nUSec ) | ||
242 | { | ||
243 | fd_set rfds; | ||
244 | struct timeval tv; | ||
245 | int retval; | ||
246 | |||
247 | /* Watch stdin (fd 0) to see when it has input. */ | ||
248 | FD_ZERO(&rfds); | ||
249 | FD_SET(nSocket, &rfds); | ||
250 | /* Wait up to five seconds. */ | ||
251 | tv.tv_sec = nSec; | ||
252 | tv.tv_usec = nUSec; | ||
253 | |||
254 | retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); | ||
255 | /* Don't rely on the value of tv now! */ | ||
256 | |||
257 | if (retval == -1) | ||
258 | { | ||
259 | // Oh my god!!! some kind of horrible problem!!!! | ||
260 | return false; | ||
261 | } | ||
262 | else if( retval ) | ||
263 | { | ||
264 | // None of them have data, but the connection is still active. | ||
265 | return readInput(); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | return true; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | bool Connection::clearOutput() | ||
274 | { | ||
275 | return xOutputBuf.clearData(); | ||
276 | } | ||
277 | |||
278 | bool Connection::clearInput() | ||
279 | { | ||
280 | return xInputBuf.clearData(); | ||
281 | } | ||
282 | |||
283 | #define min( a, b ) ((a<b)?(a):(b)) | ||
284 | |||
285 | bool Connection::writeOutput() | ||
286 | { | ||
287 | int nBytes = TEMP_FAILURE_RETRY( write( nSocket, xOutputBuf.getData(), min( 2048, xOutputBuf.getLength() ) ) ); | ||
288 | if( nBytes < 0 ) | ||
289 | { | ||
290 | perror("writeOutput"); | ||
291 | return true; | ||
292 | } | ||
293 | /* | ||
294 | if( nBytes < xOutputBuf.getLength() ) | ||
295 | { | ||
296 | printf("Havn't written all the data (%d/%d/%d%%)\n", nBytes, xOutputBuf.getLength(), nBytes/(xOutputBuf.getLength()*100) ); | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | printf("Wrote all pending data.\n"); | ||
301 | } | ||
302 | */ | ||
303 | xOutputBuf.usedData( nBytes ); | ||
304 | //clearOutput(); | ||
305 | |||
306 | return true; | ||
307 | } | ||
308 | |||
309 | bool Connection::hasOutput() | ||
310 | { | ||
311 | if( xOutputBuf.getLength() == 0 ) | ||
312 | { | ||
313 | return false; | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | return true; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | bool Connection::hasInput() | ||
322 | { | ||
323 | if( xInputBuf.getLength() == 0 ) | ||
324 | { | ||
325 | return false; | ||
326 | } | ||
327 | else | ||
328 | { | ||
329 | return true; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | bool Connection::usedInput( int nAmount ) | ||
334 | { | ||
335 | return xInputBuf.usedData( nAmount ); | ||
336 | } | ||
337 | |||
338 | bool Connection::needDisconnect() | ||
339 | { | ||
340 | return bDisconnectMe; | ||
341 | } | ||
342 | |||
343 | void Connection::disconnect() | ||
344 | { | ||
345 | bDisconnectMe = true; | ||
346 | } | ||
347 | |||
348 | void Connection::setProtocol( class Protocol *pNewProtocol ) | ||
349 | { | ||
350 | pProtocol = pNewProtocol; | ||
351 | pProtocol->setConnection( this ); | ||
352 | } | ||
353 | |||
354 | int Connection::getInputAmnt() | ||
355 | { | ||
356 | return xInputBuf.getLength(); | ||
357 | } | ||
358 | |||
359 | int Connection::getOutputAmnt() | ||
360 | { | ||
361 | return xOutputBuf.getLength(); | ||
362 | } | ||
363 | |||
364 | class Protocol *Connection::getProtocol() | ||
365 | { | ||
366 | return pProtocol; | ||
367 | } | ||
368 | |||
369 | void Connection::printInputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) | ||
370 | { | ||
371 | printDataDebug( | ||
372 | (const unsigned char *)xInputBuf.getData(), | ||
373 | xInputBuf.getLength(), | ||
374 | "input", | ||
375 | lpPrefix, | ||
376 | fh, | ||
377 | nBytesMax | ||
378 | ); | ||
379 | } | ||
380 | |||
381 | void Connection::printOutputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) | ||
382 | { | ||
383 | printDataDebug( | ||
384 | (const unsigned char *)xOutputBuf.getData(), | ||
385 | xOutputBuf.getLength(), | ||
386 | "output", | ||
387 | lpPrefix, | ||
388 | fh, | ||
389 | nBytesMax | ||
390 | ); | ||
391 | } | ||
392 | |||
393 | void Connection::printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ) | ||
394 | { | ||
395 | if( nBytesMax > 0 ) | ||
396 | { | ||
397 | nDataLen = (nBytesMax<nDataLen)?(nBytesMax):(nDataLen); | ||
398 | } | ||
399 | |||
400 | fprintf( fh, "%sDisplaying %d bytes of %s.\n", lpPrefix, nDataLen, lpName ); | ||
401 | int j = 0; | ||
402 | fprintf( fh, lpPrefix ); | ||
403 | for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); | ||
404 | for(;;) | ||
405 | { | ||
406 | fprintf( fh, lpPrefix ); | ||
407 | int kmax = 8; | ||
408 | if( nDataLen-j < 8 ) kmax = nDataLen-j; | ||
409 | for(int k = 0; k < 8; k++ ) | ||
410 | { | ||
411 | if( k < kmax ) | ||
412 | { | ||
413 | fprintf( fh, "%02X ", (int)((unsigned char)pData[j+k]) ); | ||
414 | } | ||
415 | else | ||
416 | { | ||
417 | fprintf( fh, "-- "); | ||
418 | } | ||
419 | } | ||
420 | printf("| "); | ||
421 | for(int k = 0; k < kmax; k++ ) | ||
422 | { | ||
423 | fprintf( fh, "%c ", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') ); | ||
424 | } | ||
425 | fprintf( fh, "\n"); | ||
426 | j += kmax; | ||
427 | if( j >= nDataLen ) break; | ||
428 | } | ||
429 | fprintf( fh, lpPrefix ); | ||
430 | for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); | ||
431 | } | ||
432 | |||
diff --git a/src/connection.h b/src/connection.h new file mode 100644 index 0000000..efb8630 --- /dev/null +++ b/src/connection.h | |||
@@ -0,0 +1,387 @@ | |||
1 | /**\file | ||
2 | * Contains the Connection class. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | |||
6 | #ifndef CONNECTION_H | ||
7 | #define CONNECTION_H | ||
8 | |||
9 | #include "multilog.h" | ||
10 | #include "flexbuf.h" | ||
11 | #include "protocol.h" | ||
12 | |||
13 | /** Represents a single connection on a network. While these connections | ||
14 | * may be treated more or less just like files, occasionally problems arise | ||
15 | * when writing data at any time you feel like. Therefore you run all your | ||
16 | * data through a Connection, which buffers all data and makes sure no | ||
17 | * buffers are exceeded and nothing inappropriate for the recipient of the | ||
18 | * data is sent. | ||
19 | *@author Mike Buland | ||
20 | */ | ||
21 | class Connection | ||
22 | { | ||
23 | public: | ||
24 | /** | ||
25 | * Construct a blank and non-connected Connection. The created object is | ||
26 | * not yet connected to anything, and most of the functions except open are | ||
27 | * unusable. | ||
28 | */ | ||
29 | Connection(); | ||
30 | |||
31 | /** | ||
32 | * Destroy the connection, clean up all pending data requests and close the | ||
33 | * contained socket. This does not send out pending data, especially since | ||
34 | * such an operation could take considerable time, depending on the pending | ||
35 | * data and state of the receiving end. | ||
36 | */ | ||
37 | ~Connection(); | ||
38 | |||
39 | /** | ||
40 | * Open a connection to a remote server. This sets up this connection as | ||
41 | * a client instead of a server and does all of the work that needs to be | ||
42 | * done to actually open an INET_AF connection, which is a lot of work. | ||
43 | *@param sAddr The address to connect to. This can be in any format | ||
44 | * normally understood by your system to be an address, ip, domain name, | ||
45 | * etc. | ||
46 | *@param nPort The port number to connect to on the remote server. | ||
47 | *@returns True if the connection was successful and everything is setup, | ||
48 | * false if there were any of a dozen errors and the connection is not set. | ||
49 | *@todo Make this function add log entries to a standard MultiLog if | ||
50 | * something goes wrong. | ||
51 | */ | ||
52 | bool open( const char *sAddr, int nPort ); | ||
53 | |||
54 | /** Append the given data to the output. The data is presumed to be null | ||
55 | * terminated. To put binary data into the stream, use the other | ||
56 | * appendOutput function. This should be the only method used to | ||
57 | * communicate with the socket. | ||
58 | *@param lpOutput The data to add to the output queue. | ||
59 | *@param nSize How much data is in the lpOutput buffer. If this value | ||
60 | * is -1 then the program treats lpOutput as a null-terminated string. | ||
61 | *@returns True if everything is ok, false otherwise. | ||
62 | */ | ||
63 | bool appendOutput( const char *lpOutput, int nSize=-1 ); | ||
64 | |||
65 | /** | ||
66 | * Append the character to the output. | ||
67 | *@param lOutput The character to add to the output queue. | ||
68 | *@returns True if everything is ok, false otherwise. | ||
69 | */ | ||
70 | bool appendOutput( const char lOutput ); | ||
71 | |||
72 | /** | ||
73 | * Append the short to the output. | ||
74 | *@param lOutput The short to add to the output queue. | ||
75 | *@returns True if everything is ok, false otherwise. | ||
76 | */ | ||
77 | bool appendOutput( const short lOutput ); | ||
78 | |||
79 | /** | ||
80 | * Append the int to the output. | ||
81 | *@param lOutput The int to add to the output queue. | ||
82 | *@returns True if everything is ok, false otherwise. | ||
83 | */ | ||
84 | bool appendOutput( const int lOutput ); | ||
85 | |||
86 | /** | ||
87 | * Append the long to the output. | ||
88 | *@param lOutput The long to add to the output queue. | ||
89 | *@returns True if everything is ok, false otherwise. | ||
90 | */ | ||
91 | bool appendOutput( const long lOutput ); | ||
92 | |||
93 | /** | ||
94 | * Append the float to the output. | ||
95 | *@param lOutput The float to add to the output queue. | ||
96 | *@returns True if everything is ok, false otherwise. | ||
97 | */ | ||
98 | bool appendOutput( const float lOutput ); | ||
99 | |||
100 | /** | ||
101 | * Append the double to the output. | ||
102 | *@param lOutput The double to add to the output queue. | ||
103 | *@returns True if everything is ok, false otherwise. | ||
104 | */ | ||
105 | bool appendOutput( const double lOutput ); | ||
106 | |||
107 | /** | ||
108 | * Append the unsigned char to the output. | ||
109 | *@param lOutput The unsigned char to add to the output queue. | ||
110 | *@returns True if everything is ok, false otherwise. | ||
111 | */ | ||
112 | bool appendOutput( const unsigned char lOutput ); | ||
113 | |||
114 | /** | ||
115 | * Append the unsigned short to the output. | ||
116 | *@param lOutput The unsigned short to add to the output queue. | ||
117 | *@returns True if everything is ok, false otherwise. | ||
118 | */ | ||
119 | bool appendOutput( const unsigned short lOutput ); | ||
120 | |||
121 | /** | ||
122 | * Append the unsigned int to the output. | ||
123 | *@param lOutput The unsigned int to add to the output queue. | ||
124 | *@returns True if everything is ok, false otherwise. | ||
125 | */ | ||
126 | bool appendOutput( const unsigned int lOutput ); | ||
127 | |||
128 | /** | ||
129 | * Append the unsigned long to the output. | ||
130 | *@param lOutput The unsigned long to add to the output queue. | ||
131 | *@returns True if everything is ok, false otherwise. | ||
132 | */ | ||
133 | bool appendOutput( const unsigned long lOutput ); | ||
134 | |||
135 | /** | ||
136 | * Writes all input data in the buffer in a dual-view ascii and hex display | ||
137 | * to a file. There are a number of options that also help with debugging. | ||
138 | *@param lpPrefix Text to be added to the begining of every line written | ||
139 | * out. The default is a blank string. | ||
140 | *@param fh The file to write the data to in text mode. This is stdout by | ||
141 | * default, but could be any already open file handle. | ||
142 | *@param nBytesMax The maximum number of bytes to write to the output. The | ||
143 | * amount of data can be overwhelming sometimes, so you can limit it. The | ||
144 | * default value is -1, which is also unlimited. | ||
145 | */ | ||
146 | void printInputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); | ||
147 | |||
148 | /** | ||
149 | * Writes all output data in the buffer in a dual-view ascii and hex display | ||
150 | * to a file. There are a number of options that also help with debugging. | ||
151 | *@param lpPrefix Text to be added to the begining of every line written | ||
152 | * out. The default is a blank string. | ||
153 | *@param fh The file to write the data to in text mode. This is stdout by | ||
154 | * default, but could be any already open file handle. | ||
155 | *@param nBytesMax The maximum number of bytes to write to the output. The | ||
156 | * amount of data can be overwhelming sometimes, so you can limit it. The | ||
157 | * default value is -1, which is also unlimited. | ||
158 | */ | ||
159 | void printOutputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); | ||
160 | |||
161 | /** | ||
162 | * This is the low-level generic function that is called by both | ||
163 | * printInputDebug and printOutputDebug. It works effectively just like | ||
164 | * both of them, except that you can give it a raw pointer to the data to | ||
165 | * print out. This probably doesn't belong in this class, but this was | ||
166 | * where I was when I needed it. | ||
167 | *@param pData A pointer to the data to write. This is not treated as a | ||
168 | * null terminated string, so make sure that the nDataLen param is set | ||
169 | * properly. | ||
170 | *@param nDataLen The number of bytes that are in pData and that you want to | ||
171 | * see. | ||
172 | *@param lpName The name of the data, this is used in the header where it | ||
173 | * says "Displaying nnn bytes of <lpName>." A good example would be input | ||
174 | * or output. | ||
175 | *@param lpPrefix Text to put before every line output. This just makes it | ||
176 | * easier to tell large blocks apart in the output. | ||
177 | *@param fh The file handle to write all data to. | ||
178 | *@param nBytesMax The maximum number of bytes. This parameter is stupid. | ||
179 | * If it is set to -1, then nDataLen is used, otherwise the smaller value is | ||
180 | * used as the number of bytes to output. | ||
181 | *@todo Put this function somewhere more deserving. | ||
182 | *@todo Remove the nBytesMax param, we need that in the other functions, | ||
183 | * not this one! | ||
184 | */ | ||
185 | void printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ); | ||
186 | |||
187 | /** Append the given data to the input. The data is presumed to be null | ||
188 | * terminated. To put binary data into the stream, use the other | ||
189 | * appendInput function. This is mainly used by internal routines. | ||
190 | *@param lpInput The data to add to the input queue. | ||
191 | *@param nSize How much data is in the lpInput buffer. If this value | ||
192 | * is -1 then the program treats lpOutput as a null-terminated string. | ||
193 | *@returns True if everything is ok, false otherwise. | ||
194 | */ | ||
195 | bool appendInput( const char *lpInput, int nSize=-1 ); | ||
196 | |||
197 | /** Searches through the current pending input for a certain character. | ||
198 | * This is useful for finding out where exactly the end of a line is, for | ||
199 | * example, to see if a command has been entered yet. | ||
200 | *@param cTarget The character to search for. | ||
201 | *@returns The position of the target relative to the begining of the input | ||
202 | * or -1 if the target wasn't found. | ||
203 | */ | ||
204 | int scanInputFor( char cTarget ); | ||
205 | |||
206 | /** Gets a pointer to the output buffer. This is mainly used by internal | ||
207 | * routines, and is cleared every click when data is sent out again. | ||
208 | *@returns A pointer to the buffer holding the pending output data. | ||
209 | */ | ||
210 | const char *getOutput(); | ||
211 | |||
212 | /** Gets a pointer to the start of the input buffer's active data | ||
213 | * section. Use this to gain access to the input you need to do | ||
214 | * your job. | ||
215 | *@returns A pointer to the data in the input buffer. Do not delete this. | ||
216 | */ | ||
217 | const char *getInput(); | ||
218 | |||
219 | /** Clears all pending output, this is mainly just used internally. | ||
220 | *@returns True if operation was a success, otherwise false. | ||
221 | */ | ||
222 | bool clearOutput(); | ||
223 | |||
224 | /** Clears all pending input, weather it's been used or not. Please | ||
225 | * refrain from calling this during normal operation, use usedInput | ||
226 | * instead, it's much safer. | ||
227 | *@returns True if the operation was a success, false otherwise. | ||
228 | */ | ||
229 | bool clearInput(); | ||
230 | |||
231 | /** Sets the socket that should be used internally. | ||
232 | *@param nNewSocket The new socket to work with. | ||
233 | */ | ||
234 | void setSocket( int nNewSocket ); | ||
235 | |||
236 | /** Gets the handle (number) of the working socket. This can be a | ||
237 | * dangerous function to call, please refrain from calling it directly | ||
238 | * if any alternative can be found. | ||
239 | *@returns The number of the working socket. | ||
240 | */ | ||
241 | int getSocket(); | ||
242 | |||
243 | /** Determines if the connection is still active. | ||
244 | *@returns True if the connection is active, false otherwise. | ||
245 | */ | ||
246 | bool isActive(); | ||
247 | |||
248 | /** Clears all buffers and sets up the connection to be reused. | ||
249 | * Does not actually close the socket, that's handled by the | ||
250 | * ConnectionManager | ||
251 | */ | ||
252 | void close(); | ||
253 | |||
254 | /** Opens a socket. Really just sets up the connection for use since | ||
255 | * the socket itself was created and opened by the ConnectionManager. | ||
256 | * This also calls setSocket so you don't have to. | ||
257 | *@param nNewSocket The socket to assosiate with. | ||
258 | */ | ||
259 | bool open( int nNewSocket ); | ||
260 | |||
261 | /** | ||
262 | * Reads all pending input from the connection. If this is called outside | ||
263 | * of the ConnectionManager it will usually block indefinately waiting for | ||
264 | * new data. The only way to change this behaviour is to modify the socket | ||
265 | * low-level when you connect it manually, or, preferably use the other | ||
266 | * readInput function to control blocking time. | ||
267 | *@returns True socket is still connected, otherwise false. | ||
268 | */ | ||
269 | bool readInput(); | ||
270 | |||
271 | /** | ||
272 | * Reads all pending input from the connection, blocking up to nSec | ||
273 | * seconds and nUSec micro-seconds for the data. This uses select to | ||
274 | * simulate blocking, but has the same effect as standard io blocking. | ||
275 | * If you don't want to block, just set both values to zero. | ||
276 | *@param nSec Max seconds to wait. | ||
277 | *@param nUSec Max micro-seconds to wait. | ||
278 | */ | ||
279 | bool readInput( int nSec, int nUSec ); | ||
280 | |||
281 | /** Writes all data that is pending to the socket. | ||
282 | *@returns True if all data was written succesfully, false otherwise. | ||
283 | */ | ||
284 | bool writeOutput(); | ||
285 | |||
286 | /** Determines if the connection has output waiting to go out. | ||
287 | *@returns true if there is pending output, otherwise false. | ||
288 | */ | ||
289 | bool hasOutput(); | ||
290 | |||
291 | /** Sets internal flags so that this connection will be deleted next | ||
292 | * time through the ConnectionManager. | ||
293 | */ | ||
294 | void disconnect(); | ||
295 | |||
296 | /** Determines if this connection is ready to be disconnected or not. | ||
297 | *@returns True if it is time to disconnect, false if it isn't. | ||
298 | */ | ||
299 | bool needDisconnect(); | ||
300 | |||
301 | /** Tells the caller if there is pending input waiting to be processed. | ||
302 | *@returns True if there is pending input that has not been used, returns | ||
303 | * false if there isn't. | ||
304 | */ | ||
305 | bool hasInput(); | ||
306 | |||
307 | /** Removes bytes from the begining of the input queue. Use this after | ||
308 | * getting the input and processing as much as you need to. | ||
309 | *@param nAmount The number of bytes used. | ||
310 | *@returns true if the update was successful, otherwise false. | ||
311 | */ | ||
312 | bool usedInput( int nAmount ); | ||
313 | |||
314 | /** Sets the protocol to be used by this connection. All data in and out | ||
315 | * passes through the protocol object, which may process that data to | ||
316 | * filter out and process any special messages that may have been | ||
317 | * included. Everything that isn't processed can be accessed in the | ||
318 | * standard method. | ||
319 | *@param pNewProtocol A pointer to a protocol object that you want to | ||
320 | * use. | ||
321 | */ | ||
322 | void setProtocol( class Protocol *pNewProtocol ); | ||
323 | |||
324 | /** Gets the number of bytes that are waiting in the input queue, the data | ||
325 | * that has yet to be processed. | ||
326 | *@returns The number of bytes in the input queue. | ||
327 | */ | ||
328 | int getInputAmnt(); | ||
329 | |||
330 | /** Gets the number of bytes that are waiting in the output queue, the data | ||
331 | * that has yet to be sent to the connected socket. | ||
332 | *@returns The number of bytes in the input queue. | ||
333 | */ | ||
334 | int getOutputAmnt(); | ||
335 | |||
336 | /** Gets a pointer to the protocol that is attatched to this connection | ||
337 | * object. This is useful to set modes, and send special commands in | ||
338 | * addition to the standard raw data reads and writes that are normally | ||
339 | * permitted. In fact, in everything besides a raw telnet protocol all | ||
340 | * data should be sent through the protocol and not the connection object. | ||
341 | *@returns A pointer to the Protocol assosiated with this connection. | ||
342 | */ | ||
343 | class Protocol *getProtocol(); | ||
344 | |||
345 | private: | ||
346 | /** | ||
347 | * A buffer to keep data read from the socket in. This is filled in by | ||
348 | * the function readInput, which is automatically called by the | ||
349 | * ConnectionManager whenever new data is ready. | ||
350 | */ | ||
351 | FlexBuf xInputBuf; | ||
352 | |||
353 | /** | ||
354 | * A buffer to keep data that should be sent to the socket. This is filled | ||
355 | * in by using the AppendOutput functions and is sent to the socket using | ||
356 | * the writeOutput function, which is automatically called every cycle by | ||
357 | * the ConnectionManager when there is pending data. | ||
358 | */ | ||
359 | FlexBuf xOutputBuf; | ||
360 | |||
361 | /** | ||
362 | * The socket that the user is connected to. This is not the same as the | ||
363 | * socket number of the listening socket, this is the unique socket on the | ||
364 | * system that the data is coming to. | ||
365 | */ | ||
366 | int nSocket; | ||
367 | |||
368 | /** | ||
369 | * True=active connection, False=connection lost | ||
370 | */ | ||
371 | bool bActive; | ||
372 | |||
373 | /** | ||
374 | * True=disconnect next cycle (after data is transmitted), Flse=keep going. | ||
375 | */ | ||
376 | bool bDisconnectMe; | ||
377 | |||
378 | /** | ||
379 | * A pointer to a protocol handler that can automatically process the data | ||
380 | * in the buffers. This is optional if you use the connections on your own | ||
381 | * but reccomended if you use this with the rest of the ConnectionManager | ||
382 | * system. | ||
383 | */ | ||
384 | class Protocol *pProtocol; | ||
385 | }; | ||
386 | |||
387 | #endif | ||
diff --git a/src/connectionmanager.cpp b/src/connectionmanager.cpp new file mode 100644 index 0000000..36ff961 --- /dev/null +++ b/src/connectionmanager.cpp | |||
@@ -0,0 +1,343 @@ | |||
1 | #include <time.h> | ||
2 | #include <string.h> | ||
3 | #include <stdio.h> | ||
4 | #include <errno.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <unistd.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <sys/socket.h> | ||
9 | #include <termios.h> | ||
10 | #include <netinet/in.h> | ||
11 | #include <netdb.h> | ||
12 | #include <arpa/inet.h> | ||
13 | #include "connectionmanager.h" | ||
14 | #include <fcntl.h> | ||
15 | |||
16 | ConnectionManager::ConnectionManager() | ||
17 | { | ||
18 | pLog = MultiLog::getLog(); | ||
19 | nMasterSocket = -1; | ||
20 | pMonitor = NULL; | ||
21 | } | ||
22 | |||
23 | ConnectionManager::~ConnectionManager() | ||
24 | { | ||
25 | std::list<Connection *>::const_iterator i; | ||
26 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
27 | { | ||
28 | delete (*i); | ||
29 | } | ||
30 | for( i = lInactive.begin(); i != lInactive.end(); i++ ) | ||
31 | { | ||
32 | delete (*i); | ||
33 | } | ||
34 | } | ||
35 | |||
36 | bool ConnectionManager::startServer( int nPort, int nInitPool ) | ||
37 | { | ||
38 | /* Create the socket and set it up to accept connections. */ | ||
39 | struct sockaddr_in name; | ||
40 | |||
41 | /* Create the socket. */ | ||
42 | nMasterSocket = socket (PF_INET, SOCK_STREAM, 0); | ||
43 | if (nMasterSocket < 0) | ||
44 | { | ||
45 | pLog->LineLog( MultiLog::LError, "Couldn't create a listen socket."); | ||
46 | return false; | ||
47 | } | ||
48 | |||
49 | /* Give the socket a name. */ | ||
50 | name.sin_family = AF_INET; | ||
51 | name.sin_port = htons( nPort ); | ||
52 | |||
53 | // I think this specifies who we will accept connections from, | ||
54 | // a good thing to make configurable later on | ||
55 | name.sin_addr.s_addr = htonl( INADDR_ANY ); | ||
56 | |||
57 | int opt = 1; | ||
58 | setsockopt( nMasterSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); | ||
59 | |||
60 | if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0) | ||
61 | { | ||
62 | pLog->LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); | ||
63 | return false; | ||
64 | } | ||
65 | |||
66 | if (listen (nMasterSocket, 1) < 0) | ||
67 | { | ||
68 | pLog->LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); | ||
69 | return false; | ||
70 | } | ||
71 | |||
72 | /* Initialize the set of active sockets. */ | ||
73 | FD_ZERO (&fdActive); | ||
74 | FD_ZERO (&fdRead); | ||
75 | FD_ZERO (&fdWrite); | ||
76 | FD_ZERO (&fdException); | ||
77 | FD_SET (nMasterSocket, &fdActive); | ||
78 | |||
79 | for( int j = 0; j < nInitPool; j++ ) | ||
80 | { | ||
81 | lInactive.insert( lInactive.begin(), new Connection() ); | ||
82 | } | ||
83 | |||
84 | return true; | ||
85 | } | ||
86 | |||
87 | bool ConnectionManager::startServer( int nPort, int nInitPool, int nNumTries, int nTimeout ) | ||
88 | { | ||
89 | struct timeval xTimeout; | ||
90 | |||
91 | for( int j = 0; j < nNumTries; j++ ) | ||
92 | { | ||
93 | pLog->LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); | ||
94 | if( startServer( nPort, nInitPool ) == true ) | ||
95 | { | ||
96 | return true; | ||
97 | } | ||
98 | else if( j < nNumTries-1 ) | ||
99 | { | ||
100 | pLog->LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); | ||
101 | xTimeout.tv_sec = nTimeout; | ||
102 | xTimeout.tv_usec = 0; | ||
103 | if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { | ||
104 | pLog->LineLog( MultiLog::LError, "Error using select to sleep for a while."); | ||
105 | } | ||
106 | usleep( nTimeout ); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return false; | ||
111 | } | ||
112 | |||
113 | bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) | ||
114 | { | ||
115 | struct timeval xTimeout; | ||
116 | |||
117 | xTimeout.tv_sec = nTimeout / 1000000; | ||
118 | xTimeout.tv_usec = nTimeout % 1000000; | ||
119 | |||
120 | /* Block until input arrives on one or more active sockets. */ | ||
121 | fdRead = fdActive; | ||
122 | fdWrite = fdActive; | ||
123 | fdException = fdActive; | ||
124 | |||
125 | // We removed the write checking because it just checks to see if you *can* | ||
126 | // write...that's stupid, they're all open, so it always exits immediately | ||
127 | // if there are ANY connections there... | ||
128 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 ) | ||
129 | { | ||
130 | pLog->LineLog( MultiLog::LError, "Error attempting to scan open connections."); | ||
131 | perror("ConnectionManager"); | ||
132 | return false; | ||
133 | } | ||
134 | // Now we use select to sleep as well as to scan for connections, now we | ||
135 | // just need to fix the fact that if there are no connections, the seccond | ||
136 | // select call doesn't return until there is a connection... | ||
137 | if( bForceTimeout ) | ||
138 | { | ||
139 | if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { | ||
140 | pLog->LineLog( MultiLog::LError, "Error using select to sleep for a while."); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | /* Service all the sockets with input pending. */ | ||
145 | for( int i = 0; i < FD_SETSIZE; ++i ) | ||
146 | { | ||
147 | if( FD_ISSET( i, &fdRead ) ) | ||
148 | { | ||
149 | if( i == nMasterSocket ) | ||
150 | { | ||
151 | addConnection(); | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | Connection *pCon = findActiveConnection( i ); | ||
156 | if( pCon == NULL ) | ||
157 | { | ||
158 | pLog->LineLog( MultiLog::LError, "A connection object was lost, or never created!"); | ||
159 | return false; | ||
160 | } | ||
161 | |||
162 | /* Data arriving on an already-connected socket. */ | ||
163 | if( pCon->readInput() != true ) | ||
164 | { | ||
165 | pLog->LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); | ||
166 | close( i ); | ||
167 | FD_CLR( i, &fdActive ); | ||
168 | pMonitor->onClosedConnection( pCon ); | ||
169 | pCon->close(); | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | // We actually read something...but the connection handles | ||
174 | // protocol notification, so we don't need to do anything | ||
175 | // here... | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | std::list<Connection *>::iterator i; | ||
181 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
182 | { | ||
183 | if( (*i)->isActive() == false ) | ||
184 | { | ||
185 | std::list<Connection *>::iterator l = i; | ||
186 | i--; | ||
187 | lInactive.insert( lInactive.end(), *l ); | ||
188 | lActive.erase( l ); | ||
189 | continue; | ||
190 | } | ||
191 | if( (*i)->hasOutput() ) | ||
192 | { | ||
193 | (*i)->writeOutput(); | ||
194 | } | ||
195 | if( (*i)->needDisconnect() ) | ||
196 | { | ||
197 | int prt = (*i)->getSocket(); | ||
198 | close( prt ); | ||
199 | FD_CLR( prt, &fdActive ); | ||
200 | pMonitor->onClosedConnection( *i ); | ||
201 | (*i)->close(); | ||
202 | lInactive.insert( lInactive.end(), *i ); | ||
203 | std::list<Connection *>::iterator l = i; | ||
204 | i--; | ||
205 | lActive.erase( l ); | ||
206 | pLog->LineLog( MultiLog::LStatus, "Closing connection due to server request."); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return true; | ||
211 | } | ||
212 | |||
213 | bool ConnectionManager::shutdownServer() | ||
214 | { | ||
215 | while( !lActive.empty() ) | ||
216 | { | ||
217 | Connection *i = *(lActive.begin()); | ||
218 | if( i->isActive() ) | ||
219 | { | ||
220 | i->close(); | ||
221 | pMonitor->onClosedConnection( i ); | ||
222 | lInactive.insert( lInactive.end(), i ); | ||
223 | lActive.erase( lActive.begin() ); | ||
224 | } | ||
225 | } | ||
226 | /* | ||
227 | for( int i = 0; i < nPoolSize; i++ ) | ||
228 | { | ||
229 | |||
230 | int prt = axConPool[i].getSocket(); | ||
231 | close( prt ); | ||
232 | // FD_CLR( prt, &fdActive ); | ||
233 | pMonitor->onClosedConnection( &axConPool[i] ); | ||
234 | axConPool[i].close(); | ||
235 | } | ||
236 | */ | ||
237 | shutdown( nMasterSocket, SHUT_RDWR ); | ||
238 | close( nMasterSocket ); | ||
239 | |||
240 | return true; | ||
241 | } | ||
242 | |||
243 | bool ConnectionManager::broadcastMessage( const char *lpData, int nExcludeSocket ) | ||
244 | { | ||
245 | std::list<Connection *>::const_iterator i; | ||
246 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
247 | { | ||
248 | if( (*i)->isActive() && | ||
249 | (*i)->getSocket() != nExcludeSocket ) | ||
250 | { | ||
251 | (*i)->appendOutput( lpData ); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | return true; | ||
256 | } | ||
257 | |||
258 | bool ConnectionManager::addConnection() | ||
259 | { | ||
260 | struct sockaddr_in clientname; | ||
261 | size_t size; | ||
262 | int newSocket; | ||
263 | |||
264 | size = sizeof( clientname ); | ||
265 | #ifdef __CYGWIN__ | ||
266 | newSocket = accept( nMasterSocket, (struct sockaddr *) &clientname, (int *)&size ); | ||
267 | #else | ||
268 | newSocket = accept( nMasterSocket, (struct sockaddr *) &clientname, &size ); | ||
269 | #endif | ||
270 | if( newSocket < 0 ) | ||
271 | { | ||
272 | pLog->LineLog( MultiLog::LError, "Error accepting a new connection!" ); | ||
273 | return false; | ||
274 | } | ||
275 | // char *tmpa = inet_ntoa(clientname.sin_addr); | ||
276 | char tmpa[20]; | ||
277 | inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); | ||
278 | pLog->LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); | ||
279 | /* | ||
280 | int nCnt = 0; | ||
281 | for( int j = 0; j < nPoolSize; j++ ) | ||
282 | { | ||
283 | if( axConPool[j].isActive() ) | ||
284 | { | ||
285 | nCnt++; | ||
286 | } | ||
287 | } | ||
288 | pLog->LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); | ||
289 | */ | ||
290 | // free( tmpa ); | ||
291 | FD_SET( newSocket, &fdActive ); | ||
292 | |||
293 | //void nonblock(socket_t s) | ||
294 | { | ||
295 | int flags; | ||
296 | |||
297 | flags = fcntl(newSocket, F_GETFL, 0); | ||
298 | flags |= O_NONBLOCK; | ||
299 | if (fcntl(newSocket, F_SETFL, flags) < 0) | ||
300 | { | ||
301 | return false; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | Connection *pCon = getInactiveConnection(); | ||
306 | pCon->open( newSocket ); | ||
307 | |||
308 | pMonitor->onNewConnection( pCon ); | ||
309 | |||
310 | lActive.insert( lActive.end(), pCon ); | ||
311 | |||
312 | return true; | ||
313 | } | ||
314 | |||
315 | Connection *ConnectionManager::getInactiveConnection() | ||
316 | { | ||
317 | if( lInactive.empty() ) | ||
318 | { | ||
319 | return new Connection(); | ||
320 | } | ||
321 | Connection *pCon = *(lInactive.begin()); | ||
322 | lInactive.erase( lInactive.begin() ); | ||
323 | return pCon; | ||
324 | } | ||
325 | |||
326 | Connection *ConnectionManager::findActiveConnection( int nSocket ) | ||
327 | { | ||
328 | std::list<Connection *>::const_iterator i; | ||
329 | for( i = lActive.begin(); i != lActive.end(); i++ ) | ||
330 | { | ||
331 | if( (*i)->getSocket() == nSocket ) | ||
332 | { | ||
333 | return *i; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | return NULL; | ||
338 | } | ||
339 | |||
340 | void ConnectionManager::setConnectionMonitor( ConnectionMonitor *pNewMonitor ) | ||
341 | { | ||
342 | pMonitor = pNewMonitor; | ||
343 | } | ||
diff --git a/src/connectionmanager.h b/src/connectionmanager.h new file mode 100644 index 0000000..53249a7 --- /dev/null +++ b/src/connectionmanager.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /** | ||
2 | *@file | ||
3 | * Contains the ConnectionManager. | ||
4 | *@author Mike Buland | ||
5 | */ | ||
6 | |||
7 | #ifndef CONNECTIONMANAGER_H | ||
8 | #define CONNECTIONMANAGER_H | ||
9 | |||
10 | #include "multilog.h" | ||
11 | #include "connection.h" | ||
12 | #include "connectionmonitor.h" | ||
13 | #include <sys/types.h> | ||
14 | #include <list> | ||
15 | |||
16 | /** Manges incoming network connections as a server. Creates and works with | ||
17 | * Connection objects. All operations are performed on TCP/IP v4 right now, | ||
18 | * and on a single port, although any number of connections can be handled. | ||
19 | *@author Mike Buland | ||
20 | */ | ||
21 | class ConnectionManager | ||
22 | { | ||
23 | public: | ||
24 | /** | ||
25 | * Sets up the basics, like storage for the pool, and so on. This does not | ||
26 | * actually start a server, bind to a port, or create a connection pool. | ||
27 | * That's all handled by startServer(). | ||
28 | */ | ||
29 | ConnectionManager(); | ||
30 | |||
31 | /** | ||
32 | * Cleans up everything, and even clears out all still-connected Connection | ||
33 | * objects. | ||
34 | */ | ||
35 | ~ConnectionManager(); | ||
36 | |||
37 | /** | ||
38 | * Starts a server socket and binds to it, listening for new connections. | ||
39 | *@param nPort The port to listen on. | ||
40 | *@param nInitPool The size of the initial connection pool. This will | ||
41 | * grow automatically if necesarry. | ||
42 | *@returns True if the socket was bound to the port and serving was | ||
43 | * started. False if there was a problem connecting to the port. | ||
44 | */ | ||
45 | bool startServer( int nPort, int nInitPool ); | ||
46 | |||
47 | /** | ||
48 | * This is identicle to the simpler startServer function except that it | ||
49 | * will automatically try to connect multiple times in case the first | ||
50 | * attempt or two doesn't work for some reason. Initially this was | ||
51 | * written to compensate for server sockets staying locked after they were | ||
52 | * closed for a while. | ||
53 | *@param nPort The port to listen on. | ||
54 | *@param nInitPool The size of the initial connection pool. This will | ||
55 | * grow automatically if necesarry. | ||
56 | *@param nNumTries The maximum number of times to try to connect. | ||
57 | *@param nTimeout The amount of time to wait in-between connection | ||
58 | * attempts. | ||
59 | *@returns True if the socket was bound to the port and serving was | ||
60 | * started. False if there was a problem connecting to the port. | ||
61 | */ | ||
62 | bool startServer( int nPort, int nInitPool, int nNumTries, int nTimeout ); | ||
63 | |||
64 | /** | ||
65 | * Scans all open connections, halting the calling processes until data | ||
66 | * is received or nTimeout ms have gone by. While waiting for the timeout | ||
67 | * to complete the process is placed into an idle mode. | ||
68 | *@param nTimeout The number of millisecconds to wait if there is nothing | ||
69 | * to actually do. | ||
70 | *@param bForceTimeout If set to true, this will force the scanner to wait | ||
71 | * for the timout to complete before returning, even if there was pending | ||
72 | * data. | ||
73 | */ | ||
74 | bool scanConnections( int nTimeout, bool bForceTimeout ); | ||
75 | |||
76 | /** Shutdown the server and all assosiated sockets. | ||
77 | *@returns True if every socket was closed without problem. | ||
78 | */ | ||
79 | bool shutdownServer(); | ||
80 | |||
81 | /** Sends a message directly to every connected port. | ||
82 | *@param lpData A null-terminated string of data to send. | ||
83 | *@param nExcludeSocket An optional socket to exclude from the broadcast. | ||
84 | *@returns True if every socket that should have gotten the message did. | ||
85 | */ | ||
86 | bool broadcastMessage( const char *lpData, int nExcludeSocket=-1 ); | ||
87 | |||
88 | /** Sets a monitor for the manager. The monitor is sent notifications | ||
89 | * whenever a socket is connected, disconnected, or whenever an error | ||
90 | * occurs. | ||
91 | *@param pNewMonitor A pointer to a preconstructed ConnectionMonitor | ||
92 | */ | ||
93 | void setConnectionMonitor( ConnectionMonitor *pNewMonitor ); | ||
94 | |||
95 | private: | ||
96 | /** | ||
97 | * Take care of the work of actually accepting a connection. This will | ||
98 | * accept the connection, set the initial modes, and add it to the master | ||
99 | * list of active connections, as well as fire off any messages that need | ||
100 | * to be handled by anything else. | ||
101 | *@returns True if everything worked, False otherwise. | ||
102 | */ | ||
103 | bool addConnection(); | ||
104 | |||
105 | /** | ||
106 | * Seraches the internal lists of connections for one with a specific | ||
107 | * socket. | ||
108 | *@param nSocket The socket the connection is using for communication. | ||
109 | * This is the unique socket and not the one that the connection was | ||
110 | * initially to. | ||
111 | *@returns NULL if no connection was found, otherwise a pointer to a live | ||
112 | * Connection object. | ||
113 | */ | ||
114 | Connection *findActiveConnection( int nSocket ); | ||
115 | |||
116 | /** | ||
117 | * Searches the connection pool for an object that isn't in use yet, and | ||
118 | * returns it, ready to be filled in and used. | ||
119 | *@returns An unused connection object ready for use. | ||
120 | *@todo Check this code over to insure that the pool grows appropriately | ||
121 | * when enough extra connections are detected. | ||
122 | */ | ||
123 | Connection *getInactiveConnection(); | ||
124 | |||
125 | MultiLog *pLog; /**< A pointer to the active MultiLog */ | ||
126 | int nMasterSocket; /**< The listening or server socket. */ | ||
127 | fd_set fdActive; /**< The active socket set. */ | ||
128 | fd_set fdRead; /**< The sockets ready for a read. */ | ||
129 | fd_set fdWrite; /**< The sockets ready for a write. */ | ||
130 | fd_set fdException; /**< The sockets that have gotten errors. */ | ||
131 | std::list<Connection *> lInactive; /**< The pool of inactive Connections */ | ||
132 | std::list<Connection *> lActive; /**< The pool of active Connections */ | ||
133 | |||
134 | /** The ConnectionMonitor to notify of new connections. */ | ||
135 | ConnectionMonitor *pMonitor; | ||
136 | }; | ||
137 | |||
138 | #endif | ||
diff --git a/src/connectionmonitor.cpp b/src/connectionmonitor.cpp new file mode 100644 index 0000000..1b49f5d --- /dev/null +++ b/src/connectionmonitor.cpp | |||
@@ -0,0 +1,23 @@ | |||
1 | /*************************************************************************** | ||
2 | connectionmonitor.cpp - description | ||
3 | ------------------- | ||
4 | begin : Mon Sep 8 2003 | ||
5 | copyright : (C) 2003 by Mike Buland | ||
6 | email : eichlan@yf-soft.com | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include "connectionmonitor.h" | ||
19 | |||
20 | ConnectionMonitor::ConnectionMonitor(){ | ||
21 | } | ||
22 | ConnectionMonitor::~ConnectionMonitor(){ | ||
23 | } | ||
diff --git a/src/connectionmonitor.h b/src/connectionmonitor.h new file mode 100644 index 0000000..b96b533 --- /dev/null +++ b/src/connectionmonitor.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /**@file | ||
2 | * Describes the ConnectionMonitor class. | ||
3 | */ | ||
4 | #ifndef CONNECTIONMONITOR_H | ||
5 | #define CONNECTIONMONITOR_H | ||
6 | |||
7 | #include "connection.h" | ||
8 | |||
9 | /** Connection Monitor defines the base class of the objects that will be | ||
10 | * notified whenever a connection is created or destroyed. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class ConnectionMonitor | ||
14 | { | ||
15 | public: | ||
16 | /** | ||
17 | * This is only here for completeness. It does nothing. | ||
18 | */ | ||
19 | ConnectionMonitor(); | ||
20 | |||
21 | /** | ||
22 | * This is only here for completeness. It does nothing. | ||
23 | */ | ||
24 | virtual ~ConnectionMonitor(); | ||
25 | |||
26 | /** Receives the notification that new connection was received. | ||
27 | *@param pCon The connection that was created. | ||
28 | *@returns Should return a true value if everything is OK, a false to | ||
29 | * force a shutdown. | ||
30 | */ | ||
31 | virtual bool onNewConnection( Connection *pCon ) = 0; | ||
32 | |||
33 | /** Receives the notification that a connection was closed. | ||
34 | *@param pCon The connection that was closed. | ||
35 | *@returns Should return a true value if everything is OK, a false to | ||
36 | * force a shutdown. | ||
37 | */ | ||
38 | virtual bool onClosedConnection( Connection *pCon ) = 0; | ||
39 | }; | ||
40 | |||
41 | #endif | ||
diff --git a/src/flexbuf.cpp b/src/flexbuf.cpp new file mode 100644 index 0000000..acd55a7 --- /dev/null +++ b/src/flexbuf.cpp | |||
@@ -0,0 +1,206 @@ | |||
1 | #include "flexbuf.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | FlexBuf::FlexBuf() | ||
5 | { | ||
6 | lpBuf = new char[1024]; | ||
7 | nLastChar = 0; | ||
8 | nFirstChar = 0; | ||
9 | nSize = 1024; | ||
10 | nFill = 0; | ||
11 | clearData(); | ||
12 | } | ||
13 | |||
14 | FlexBuf::~FlexBuf() | ||
15 | { | ||
16 | delete[] lpBuf; | ||
17 | } | ||
18 | |||
19 | bool FlexBuf::appendData( const char *lpData, int nDSize ) | ||
20 | { | ||
21 | int nStrLen; | ||
22 | if( nDSize < 0 ) | ||
23 | { | ||
24 | nStrLen = strlen( lpData ); | ||
25 | } | ||
26 | else | ||
27 | { | ||
28 | nStrLen = nDSize; | ||
29 | } | ||
30 | |||
31 | if( nLastChar + nStrLen + 1 > nSize ) | ||
32 | { | ||
33 | if( nFill + nStrLen + 1 < nSize ) | ||
34 | { | ||
35 | memcpy( lpBuf, lpBuf+nFirstChar, nFill ); | ||
36 | nLastChar -= nFirstChar; | ||
37 | nFirstChar = 0; | ||
38 | } | ||
39 | else | ||
40 | { | ||
41 | nSize += nStrLen+1; | ||
42 | char *lpNewBuf = new char[nSize]; | ||
43 | memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); | ||
44 | delete[] lpBuf; | ||
45 | lpBuf = lpNewBuf; | ||
46 | nLastChar -= nFirstChar; | ||
47 | nFirstChar = 0; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | memcpy( &lpBuf[nLastChar], lpData, nStrLen ); | ||
52 | nLastChar += nStrLen; | ||
53 | nFill += nStrLen; | ||
54 | lpBuf[nLastChar] = '\0'; | ||
55 | |||
56 | return true; | ||
57 | } | ||
58 | |||
59 | bool FlexBuf::appendData( const char lData ) | ||
60 | { | ||
61 | if( nLastChar + 2 > nSize ) | ||
62 | { | ||
63 | if( nFill+2 < nSize ) | ||
64 | { | ||
65 | memcpy( lpBuf, lpBuf+nFirstChar, nFill ); | ||
66 | nLastChar -= nFirstChar; | ||
67 | nFirstChar = 0; | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | nSize += 1024; | ||
72 | char *lpNewBuf = new char[nSize]; | ||
73 | memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); | ||
74 | delete[] lpBuf; | ||
75 | lpBuf = lpNewBuf; | ||
76 | nLastChar -= nFirstChar; | ||
77 | nFirstChar = 0; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | lpBuf[nLastChar] = lData; | ||
82 | nLastChar++; | ||
83 | nFill++; | ||
84 | lpBuf[nLastChar] = '\0'; | ||
85 | |||
86 | return true; | ||
87 | } | ||
88 | |||
89 | bool FlexBuf::appendData( const short lData ) | ||
90 | { | ||
91 | return appendData( (const char *)&lData, sizeof(short) ); | ||
92 | } | ||
93 | |||
94 | bool FlexBuf::appendData( const int lData ) | ||
95 | { | ||
96 | return appendData( (const char *)&lData, sizeof(int) ); | ||
97 | } | ||
98 | |||
99 | bool FlexBuf::appendData( const long lData ) | ||
100 | { | ||
101 | return appendData( (const char *)&lData, sizeof(long) ); | ||
102 | } | ||
103 | |||
104 | bool FlexBuf::appendData( const float lData ) | ||
105 | { | ||
106 | return appendData( (const char *)&lData, sizeof(float) ); | ||
107 | } | ||
108 | |||
109 | bool FlexBuf::appendData( const double lData ) | ||
110 | { | ||
111 | return appendData( (const char *)&lData, sizeof(double) ); | ||
112 | } | ||
113 | |||
114 | bool FlexBuf::appendData( const unsigned char lData ) | ||
115 | { | ||
116 | return appendData( (const char)lData ); | ||
117 | } | ||
118 | |||
119 | bool FlexBuf::appendData( const unsigned short lData ) | ||
120 | { | ||
121 | return appendData( (const char *)&lData, sizeof(short) ); | ||
122 | } | ||
123 | |||
124 | bool FlexBuf::appendData( const unsigned long lData ) | ||
125 | { | ||
126 | return appendData( (const char *)&lData, sizeof(long) ); | ||
127 | } | ||
128 | |||
129 | bool FlexBuf::appendData( const unsigned int lData ) | ||
130 | { | ||
131 | return appendData( (const char *)&lData, sizeof(int) ); | ||
132 | } | ||
133 | |||
134 | bool FlexBuf::clearData() | ||
135 | { | ||
136 | nFirstChar = nLastChar = nFill = 0; | ||
137 | lpBuf[nLastChar] = '\0'; | ||
138 | |||
139 | return true; | ||
140 | } | ||
141 | |||
142 | const char *FlexBuf::getData() | ||
143 | { | ||
144 | return (lpBuf+nFirstChar); | ||
145 | } | ||
146 | |||
147 | int FlexBuf::getLength() | ||
148 | { | ||
149 | return nFill; | ||
150 | } | ||
151 | |||
152 | int FlexBuf::getCapacity() | ||
153 | { | ||
154 | return nSize; | ||
155 | } | ||
156 | |||
157 | bool FlexBuf::usedData( int nAmount ) | ||
158 | { | ||
159 | // Remove from the end if negative | ||
160 | if( nAmount < 0 ) | ||
161 | { | ||
162 | if( nFill+nAmount < 0 ) | ||
163 | { | ||
164 | nFill = nFirstChar = nLastChar = 0; | ||
165 | return true; | ||
166 | } | ||
167 | nLastChar += nAmount; | ||
168 | nFill += nAmount; | ||
169 | return true; | ||
170 | } | ||
171 | if( nAmount > nFill ) | ||
172 | { | ||
173 | nAmount = nSize; | ||
174 | // return false; | ||
175 | } | ||
176 | |||
177 | //nLastChar -= nAmount; | ||
178 | nFirstChar += nAmount; | ||
179 | nFill -= nAmount; | ||
180 | |||
181 | if( nFill == 0 ) | ||
182 | { | ||
183 | nFirstChar = nLastChar = 0; | ||
184 | } | ||
185 | |||
186 | //if( nLastChar > 0 ) | ||
187 | //{ | ||
188 | //memmove( lpBuf, &lpBuf[nAmount], nLastChar ); | ||
189 | //} | ||
190 | |||
191 | return true; | ||
192 | } | ||
193 | |||
194 | int FlexBuf::findChar( char cTarget ) | ||
195 | { | ||
196 | for( int j = nFirstChar; j < nLastChar; j++ ) | ||
197 | { | ||
198 | if( lpBuf[j] == cTarget ) | ||
199 | { | ||
200 | return j; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | return -1; | ||
205 | } | ||
206 | |||
diff --git a/src/flexbuf.h b/src/flexbuf.h new file mode 100644 index 0000000..5ce4a89 --- /dev/null +++ b/src/flexbuf.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /**\flexbuf.h | ||
2 | * Describes the FlexBuf class. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | |||
6 | #ifndef FLEXBUF_H | ||
7 | #define FLEXBUF_H | ||
8 | |||
9 | /** Stores any amount of data, but starts small, growing as necesarry. | ||
10 | * It is optimized to work with stream type situations, with data being | ||
11 | * added to the end while it is being taken from the begning. | ||
12 | *@todo Set this class up to auto-shrink back to a specified sized buffer each | ||
13 | * time it has shrunk below that for enough operations. | ||
14 | *@author Mike Buland | ||
15 | */ | ||
16 | class FlexBuf | ||
17 | { | ||
18 | public: | ||
19 | /** | ||
20 | * Construct a blank FlexBuf containing about 1k of buffer space. | ||
21 | */ | ||
22 | FlexBuf(); | ||
23 | |||
24 | /** | ||
25 | * Clean up the FlexBuf, delete all buffers. | ||
26 | */ | ||
27 | ~FlexBuf(); | ||
28 | |||
29 | /** Appends a whole string of data to the buffer. The string | ||
30 | * must be null terminated. | ||
31 | *@param lpData The data to append to the buffer. | ||
32 | *@param nDSize The size of the data described by lpData. If this | ||
33 | * value is -1 lpData is treated as a null-terminated string. | ||
34 | *@returns True if no problems occured, false otherwise. | ||
35 | */ | ||
36 | bool appendData( const char *lpData, int nDSize=-1 ); | ||
37 | |||
38 | /** Appends a single character to the end of the buffer. | ||
39 | *@param lData The character to append to the buffer. | ||
40 | *@returns True if no problems occured, false otherwise. | ||
41 | */ | ||
42 | bool appendData( const char lData ); | ||
43 | |||
44 | /** | ||
45 | * Append the short to the buffer. | ||
46 | *@param lData The short to add to the buffer queue. | ||
47 | *@returns True if everything is ok, false otherwise. | ||
48 | */ | ||
49 | bool appendData( const short lData ); | ||
50 | |||
51 | /** | ||
52 | * Append the int to the buffer. | ||
53 | *@param lData The int to add to the buffer queue. | ||
54 | *@returns True if everything is ok, false otherwise. | ||
55 | */ | ||
56 | bool appendData( const int lData ); | ||
57 | |||
58 | /** | ||
59 | * Append the long to the buffer. | ||
60 | *@param lData The long to add to the buffer queue. | ||
61 | *@returns True if everything is ok, false otherwise. | ||
62 | */ | ||
63 | bool appendData( const long lData ); | ||
64 | |||
65 | /** | ||
66 | * Append the float to the buffer. | ||
67 | *@param lData The float to add to the buffer queue. | ||
68 | *@returns True if everything is ok, false otherwise. | ||
69 | */ | ||
70 | bool appendData( const float lData ); | ||
71 | |||
72 | /** | ||
73 | * Append the double to the buffer. | ||
74 | *@param lData The double to add to the buffer queue. | ||
75 | *@returns True if everything is ok, false otherwise. | ||
76 | */ | ||
77 | bool appendData( const double lData ); | ||
78 | |||
79 | /** | ||
80 | * Append the unsigned char to the buffer. | ||
81 | *@param lData The unsigned char to add to the buffer queue. | ||
82 | *@returns True if everything is ok, false otherwise. | ||
83 | */ | ||
84 | bool appendData( const unsigned char lData ); | ||
85 | |||
86 | /** | ||
87 | * Append the unsigned short to the buffer. | ||
88 | *@param lData The unsigned short to add to the buffer queue. | ||
89 | *@returns True if everything is ok, false otherwise. | ||
90 | */ | ||
91 | bool appendData( const unsigned short lData ); | ||
92 | |||
93 | /** | ||
94 | * Append the unsigned int to the buffer. | ||
95 | *@param lData The unsigned int to add to the buffer queue. | ||
96 | *@returns True if everything is ok, false otherwise. | ||
97 | */ | ||
98 | bool appendData( const unsigned int lData ); | ||
99 | |||
100 | /** | ||
101 | * Append the unsigned long to the buffer. | ||
102 | *@param lData The unsigned long to add to the buffer queue. | ||
103 | *@returns True if everything is ok, false otherwise. | ||
104 | */ | ||
105 | bool appendData( const unsigned long lData ); | ||
106 | |||
107 | /** Removes all pending data from the buffer. | ||
108 | *@returns True if no problems occured, false otherwise. | ||
109 | */ | ||
110 | bool clearData(); | ||
111 | |||
112 | /** Gets a pointer to the internal buffer, at the begining of the current | ||
113 | * data stream. | ||
114 | *@returns A pointer to the internal data buffer. | ||
115 | */ | ||
116 | const char *getData(); | ||
117 | |||
118 | /** Gets the length of the current buffer (how much data is really in the | ||
119 | * buffer, not it's current capacity, for that check getCapacity) | ||
120 | *@returns The length of the current buffer. | ||
121 | */ | ||
122 | int getLength(); | ||
123 | |||
124 | /** Gets the current capacity of the FlexBuf. If the size nears this value | ||
125 | * then the entire buffer is resized to accomidate more data. | ||
126 | *@returns The current capacity of the FlexBuf. | ||
127 | */ | ||
128 | int getCapacity(); | ||
129 | |||
130 | /** | ||
131 | * Removes nAmount bytes from the begning of the buffer. Actually, if | ||
132 | * nAmount happens to be negative it will remove tha absolute value of | ||
133 | * nValue bytes from the end of the buffer, like the old delData command. | ||
134 | *@param nAmount The number of bytes used. | ||
135 | *@returns True if everything was successful, false if there was an error. | ||
136 | */ | ||
137 | bool usedData( int nAmount ); | ||
138 | |||
139 | /** Finds the first instance of the given character in the buffer and | ||
140 | * returns an index to it. | ||
141 | *@param cTarget The character you're looking for. | ||
142 | *@returns The index of the first instance of the given character, or | ||
143 | * -1 if it just wasn't found. | ||
144 | */ | ||
145 | int findChar( char cTarget ); | ||
146 | |||
147 | private: | ||
148 | /** The raw storage location of the FlexBuf. */ | ||
149 | char *lpBuf; | ||
150 | /** The real size of the FlexBuf. */ | ||
151 | int nSize; | ||
152 | /** Where the last char is. */ | ||
153 | int nLastChar; | ||
154 | /** Where the first char is. */ | ||
155 | int nFirstChar; | ||
156 | /** The amount of real data in the FlexBuf. This is effectively nLastChar-nFirstChar. */ | ||
157 | int nFill; | ||
158 | }; | ||
159 | |||
160 | #endif | ||
diff --git a/src/hashfunction.cpp b/src/hashfunction.cpp new file mode 100644 index 0000000..51f2259 --- /dev/null +++ b/src/hashfunction.cpp | |||
@@ -0,0 +1,10 @@ | |||
1 | #include "hashfunction.h" | ||
2 | |||
3 | HashFunction::HashFunction() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | HashFunction::~HashFunction() | ||
8 | { | ||
9 | } | ||
10 | |||
diff --git a/src/hashfunction.h b/src/hashfunction.h new file mode 100644 index 0000000..cbcf70f --- /dev/null +++ b/src/hashfunction.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef HASH_FUNCTION | ||
2 | #define HASH_FUNCTION | ||
3 | |||
4 | /** This represents the shell of a hash function. It must be aggregated in | ||
5 | * order to be used. Please read about it's two functions for specificatins | ||
6 | * relating to what values will be passed to them and what they should return | ||
7 | * for creating your own hash functions. | ||
8 | *@author Mike Buland. | ||
9 | */ | ||
10 | class HashFunction | ||
11 | { | ||
12 | public: | ||
13 | /** | ||
14 | * Standard Constructor. | ||
15 | */ | ||
16 | HashFunction(); | ||
17 | |||
18 | /** | ||
19 | * Standard Deconstructor. | ||
20 | */ | ||
21 | virtual ~HashFunction(); | ||
22 | |||
23 | /** Hashes the value represnted by id. This must return a fairly unique | ||
24 | * number in the range of 0-2^32 (or whatever the size of an unsigned long | ||
25 | * is on your system) based on the id given. The faster the number changes | ||
26 | * the better in a general sence. The return value will be the index | ||
27 | * (after probing takes place) to the data assosiated with an id, so this | ||
28 | * function should always produce the same number for any given id. | ||
29 | *@param id The identifier to use to create a unique numerical identifier. | ||
30 | *@returns A mostly unique numerical identifier generated using the given | ||
31 | * id. | ||
32 | */ | ||
33 | virtual unsigned long int hash( const void *id ) = 0; | ||
34 | |||
35 | /** This function must compare two ids in the format that this hashfunction | ||
36 | * accepts. For example, if the hash function hashes strings it should | ||
37 | * probably { return strcmp( id1, id2 ) == 0 }. | ||
38 | *@param id1 One value to use in the comparison | ||
39 | *@param id2 Another value to use in the comparison | ||
40 | *@returns True if the two values match, otherwise false. | ||
41 | */ | ||
42 | virtual bool cmpIDs( const void *id1, const void *id2 ) = 0; | ||
43 | |||
44 | // virtual void *createPersistantID( const void *id ) = 0; | ||
45 | // virtual void destroyPersistantID( const void *id ) = 0; | ||
46 | }; | ||
47 | |||
48 | #endif | ||
diff --git a/src/hashfunctioncasestring.cpp b/src/hashfunctioncasestring.cpp new file mode 100644 index 0000000..6361f45 --- /dev/null +++ b/src/hashfunctioncasestring.cpp | |||
@@ -0,0 +1,39 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | #include <ctype.h> | ||
4 | #include "hashfunctioncasestring.h" | ||
5 | |||
6 | HashFunctionCaseString::HashFunctionCaseString() | ||
7 | { | ||
8 | } | ||
9 | |||
10 | HashFunctionCaseString::~HashFunctionCaseString() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | unsigned long int HashFunctionCaseString::hash( const void *id ) | ||
15 | { | ||
16 | const char *str = (const char *)id; | ||
17 | unsigned long int nPos = 0; | ||
18 | for( int j = 0; str[j] != '\0'; j++ ) | ||
19 | { | ||
20 | nPos = tolower(str[j]) + (nPos << 6) + (nPos << 16) - nPos; | ||
21 | // nPos += nPos<<16|(((unsigned long int)tolower(str[j]))<<((j*7)%24)); | ||
22 | } | ||
23 | return nPos; | ||
24 | } | ||
25 | |||
26 | bool HashFunctionCaseString::cmpIDs( const void *id1, const void *id2 ) | ||
27 | { | ||
28 | const char *str1 = (const char *)id1; | ||
29 | const char *str2 = (const char *)id2; | ||
30 | |||
31 | int j; | ||
32 | for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) | ||
33 | { | ||
34 | if( tolower(str1[j]) != tolower(str2[j]) ) | ||
35 | return false; | ||
36 | } | ||
37 | return (str1[j]==str2[j]); | ||
38 | } | ||
39 | |||
diff --git a/src/hashfunctioncasestring.h b/src/hashfunctioncasestring.h new file mode 100644 index 0000000..9ca3d48 --- /dev/null +++ b/src/hashfunctioncasestring.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef HASH_FUNCTION_CASE_STRING | ||
2 | #define HASH_FUNCTION_CASE_STRING | ||
3 | |||
4 | #include "hashfunction.h" | ||
5 | |||
6 | /** A hash function for string data. This hash function does strings, but is | ||
7 | * actually generalized to handle any binary stream of characters terminated | ||
8 | * by a null character. This is different than HashFunctionString in that | ||
9 | * this does comparisons without regaurd to case. | ||
10 | *@author Mike Buland. | ||
11 | */ | ||
12 | class HashFunctionCaseString : public HashFunction | ||
13 | { | ||
14 | public: | ||
15 | /** | ||
16 | * Standard Constructor. | ||
17 | */ | ||
18 | HashFunctionCaseString(); | ||
19 | |||
20 | /** | ||
21 | * Standard Deconstructor. | ||
22 | */ | ||
23 | ~HashFunctionCaseString(); | ||
24 | unsigned long int hash( const void *id ); | ||
25 | bool cmpIDs( const void *id1, const void *id2 ); | ||
26 | }; | ||
27 | |||
28 | #endif | ||
diff --git a/src/hashfunctionint.cpp b/src/hashfunctionint.cpp new file mode 100644 index 0000000..4bd0feb --- /dev/null +++ b/src/hashfunctionint.cpp | |||
@@ -0,0 +1,20 @@ | |||
1 | #include "hashfunctionint.h" | ||
2 | |||
3 | HashFunctionInt::HashFunctionInt() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | HashFunctionInt::~HashFunctionInt() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | unsigned long int HashFunctionInt::hash( const void *id ) | ||
12 | { | ||
13 | return (unsigned long)(id); | ||
14 | } | ||
15 | |||
16 | bool HashFunctionInt::cmpIDs( const void *id1, const void *id2 ) | ||
17 | { | ||
18 | return (unsigned long)(id1) == (unsigned long)(id2); | ||
19 | } | ||
20 | |||
diff --git a/src/hashfunctionint.h b/src/hashfunctionint.h new file mode 100644 index 0000000..57bce89 --- /dev/null +++ b/src/hashfunctionint.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef HASH_FUNCTION_INT | ||
2 | #define HASH_FUNCTION_INT | ||
3 | |||
4 | #include "hashfunction.h" | ||
5 | |||
6 | /** A hash function for integer data. Really, this does almost nothing except | ||
7 | * ensure we're dealing with positive indicies. | ||
8 | *@author Mike Buland. | ||
9 | */ | ||
10 | class HashFunctionInt : public HashFunction | ||
11 | { | ||
12 | public: | ||
13 | /** | ||
14 | * Standard Constructor. | ||
15 | */ | ||
16 | HashFunctionInt(); | ||
17 | |||
18 | /** | ||
19 | * Standard Deconstructor. | ||
20 | */ | ||
21 | ~HashFunctionInt(); | ||
22 | unsigned long int hash( const void *id ); | ||
23 | bool cmpIDs( const void *id1, const void *id2 ); | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/src/hashfunctionstring.cpp b/src/hashfunctionstring.cpp new file mode 100644 index 0000000..8ea9f57 --- /dev/null +++ b/src/hashfunctionstring.cpp | |||
@@ -0,0 +1,36 @@ | |||
1 | #include "hashfunctionstring.h" | ||
2 | |||
3 | HashFunctionString::HashFunctionString() | ||
4 | { | ||
5 | } | ||
6 | |||
7 | HashFunctionString::~HashFunctionString() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | unsigned long int HashFunctionString::hash( const void *id ) | ||
12 | { | ||
13 | const char *str = (const char *)id; | ||
14 | unsigned long int nPos = 0; | ||
15 | for( int j = 0; str[j] != '\0'; j++ ) | ||
16 | { | ||
17 | nPos = str[j] + (nPos << 6) + (nPos << 16) - nPos; | ||
18 | // nPos += nPos<<16|(((unsigned long int)str[j])<<((j*7)%24)); | ||
19 | } | ||
20 | return nPos; | ||
21 | } | ||
22 | |||
23 | bool HashFunctionString::cmpIDs( const void *id1, const void *id2 ) | ||
24 | { | ||
25 | const char *str1 = (const char *)id1; | ||
26 | const char *str2 = (const char *)id2; | ||
27 | |||
28 | int j; | ||
29 | for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) | ||
30 | { | ||
31 | if( str1[j] != str2[j] ) | ||
32 | return false; | ||
33 | } | ||
34 | return (str1[j]==str2[j]); | ||
35 | } | ||
36 | |||
diff --git a/src/hashfunctionstring.h b/src/hashfunctionstring.h new file mode 100644 index 0000000..566f8ae --- /dev/null +++ b/src/hashfunctionstring.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef HASH_FUNCTION_STRING | ||
2 | #define HASH_FUNCTION_STRING | ||
3 | |||
4 | #include "hashfunction.h" | ||
5 | |||
6 | /** A hash function for string data. This hash function does strings, but is | ||
7 | * actually generalized to handle any binary stream of characters terminated | ||
8 | * by a null character. | ||
9 | *@author Mike Buland. | ||
10 | */ | ||
11 | class HashFunctionString : public HashFunction | ||
12 | { | ||
13 | public: | ||
14 | /** | ||
15 | * Standard Constructor. | ||
16 | */ | ||
17 | HashFunctionString(); | ||
18 | |||
19 | /** | ||
20 | * Standard Deconstructor. | ||
21 | */ | ||
22 | ~HashFunctionString(); | ||
23 | unsigned long int hash( const void *id ); | ||
24 | bool cmpIDs( const void *id1, const void *id2 ); | ||
25 | }; | ||
26 | |||
27 | #endif | ||
diff --git a/src/hashtable.cpp b/src/hashtable.cpp new file mode 100644 index 0000000..9dfe653 --- /dev/null +++ b/src/hashtable.cpp | |||
@@ -0,0 +1,345 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdio.h> | ||
3 | #include <math.h> | ||
4 | |||
5 | #include "hashtable.h" | ||
6 | |||
7 | HashTable::HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes ) | ||
8 | { | ||
9 | hFunc = hNewFunc; | ||
10 | nTableSize = nextPrime( nInitSize ); | ||
11 | aTable = new HashNode[nTableSize]; | ||
12 | //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); | ||
13 | nSize = 0; | ||
14 | nFilled = 0; | ||
15 | this->bAllowDupes = bAllowDupes; | ||
16 | } | ||
17 | |||
18 | HashTable::~HashTable() | ||
19 | { | ||
20 | delete[] aTable; | ||
21 | delete hFunc; | ||
22 | } | ||
23 | |||
24 | void HashTable::set( int j, const void *newID, const void *newData ) | ||
25 | { | ||
26 | if( newData == NULL ) | ||
27 | { | ||
28 | printf("Inserting NULL data is indestinguishable from uninserted data!\n"); | ||
29 | } | ||
30 | aTable[j].id = newID; | ||
31 | aTable[j].data = newData; | ||
32 | } | ||
33 | |||
34 | bool HashTable::isFilled( int j ) | ||
35 | { | ||
36 | return (aTable[j].id != NULL)||(aTable[j].bDeleted); | ||
37 | } | ||
38 | |||
39 | bool HashTable::reHash( unsigned long int nNewSize ) | ||
40 | { | ||
41 | HashNode *aOldTable = aTable; | ||
42 | unsigned long int oldSize = nTableSize; | ||
43 | |||
44 | // If the table can still be used if we just get rid of deleted items, don't | ||
45 | // change the size of the table, otherwise, go ahead and use the number | ||
46 | // passed in. | ||
47 | if( nSize > nTableSize>>1 ) | ||
48 | { | ||
49 | nTableSize = nextPrime( nNewSize ); | ||
50 | } | ||
51 | |||
52 | aTable = newTable( nTableSize ); | ||
53 | //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); | ||
54 | |||
55 | nSize = 0; | ||
56 | nFilled = 0; | ||
57 | |||
58 | for( unsigned long int j = 0; j < oldSize; j++ ) | ||
59 | { | ||
60 | if( aOldTable[j].id != NULL && aOldTable[j].bDeleted == false ) | ||
61 | { | ||
62 | insert( aOldTable[j].id, aOldTable[j].data ); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | delete[] aOldTable; | ||
67 | } | ||
68 | |||
69 | unsigned long int HashTable::probe( unsigned long int nStart, const void *id ) | ||
70 | { | ||
71 | int nHash = nStart; | ||
72 | nStart = nStart%nTableSize; | ||
73 | if( bAllowDupes == true ) | ||
74 | { | ||
75 | for( | ||
76 | unsigned long int j=0; | ||
77 | isFilled( nStart ) && j < 32; | ||
78 | nStart = (nStart+(1<<j))%nTableSize, j++ | ||
79 | ); | ||
80 | |||
81 | /** | ||
82 | * This is an ugly little hack. If the hash table is too full in allow- | ||
83 | * dups mode we have to fall back on a linear search, otherwise you can | ||
84 | * only get up to 32 entries with the same name. | ||
85 | */ | ||
86 | if( isFilled( nStart ) ) | ||
87 | { | ||
88 | int nOldStart = nStart; | ||
89 | for( | ||
90 | nStart++; | ||
91 | isFilled( nStart ) && nStart != nOldStart; | ||
92 | nStart = (nStart+1)%nTableSize | ||
93 | ); | ||
94 | } | ||
95 | } | ||
96 | else | ||
97 | { | ||
98 | for( | ||
99 | unsigned long int j=0; | ||
100 | isFilled( nStart ) && j < 32; | ||
101 | nStart = (nStart+(1<<j))%nTableSize, j++ | ||
102 | ) | ||
103 | { | ||
104 | if( isFilled( nStart ) ) | ||
105 | { | ||
106 | if( hFunc->cmpIDs( aTable[nStart].id, id ) == true && | ||
107 | aTable[nStart].bDeleted == false ) | ||
108 | { | ||
109 | return nStart; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | // This is our insurance, if the table is full, then go ahead and rehash, | ||
115 | // then try again. | ||
116 | if( isFilled( nStart ) ) | ||
117 | { | ||
118 | reHash( getCapacity()*2 ); | ||
119 | return probe( nHash, id ); | ||
120 | } | ||
121 | return nStart; | ||
122 | } | ||
123 | |||
124 | HashTable::HashNode *HashTable::newTable( unsigned long int nNewSize ) | ||
125 | { | ||
126 | return new HashNode[nNewSize]; | ||
127 | } | ||
128 | |||
129 | #ifdef HASH_DEBUG_VIS | ||
130 | void HashTable::printDebugLine( const char *exData ) | ||
131 | { | ||
132 | char *buf = new char[getCapacity()+3]; | ||
133 | int j; | ||
134 | buf[0] = '['; | ||
135 | for( j = 0; j < getCapacity(); j++ ) | ||
136 | { | ||
137 | buf[j+1] = (aTable[j].bDeleted)?('X'):((isFilled( j ))?('#'):('-')); | ||
138 | } | ||
139 | buf[j+1] = ']'; | ||
140 | buf[j+2] = '\0'; | ||
141 | printf("%s %s\n", buf, exData ); | ||
142 | delete[] buf; | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | bool HashTable::insert( const void *id, const void *data ) | ||
147 | { | ||
148 | unsigned long int nPos = probe( hFunc->hash( id ), id )%nTableSize; | ||
149 | |||
150 | if( bAllowDupes == true ) | ||
151 | { | ||
152 | if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) | ||
153 | { | ||
154 | set( nPos, id, data ); | ||
155 | #ifdef HASH_DEBUG_VIS | ||
156 | printDebugLine( (const char *)id ); | ||
157 | #endif | ||
158 | nSize++; | ||
159 | nFilled++; | ||
160 | return true; | ||
161 | } | ||
162 | else | ||
163 | { | ||
164 | return false; | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) | ||
170 | { | ||
171 | set( nPos, id, data ); | ||
172 | #ifdef HASH_DEBUG_VIS | ||
173 | printDebugLine( (const char *)id ); | ||
174 | #endif | ||
175 | nSize++; | ||
176 | nFilled++; | ||
177 | return true; | ||
178 | } | ||
179 | else if( hFunc->cmpIDs( aTable[nPos].id, id ) == true ) | ||
180 | { | ||
181 | set( nPos, id, data ); | ||
182 | #ifdef HASH_DEBUG_VIS | ||
183 | printDebugLine( (const char *)id ); | ||
184 | #endif | ||
185 | return true; | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | return false; | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | const void *HashTable::get( const void *id, unsigned long int nSkip ) | ||
195 | { | ||
196 | unsigned long int nPos = hFunc->hash( id )%nTableSize; | ||
197 | |||
198 | for( unsigned long int j=0; j < 32; nPos = (nPos+(1<<j))%nTableSize, j++ ) | ||
199 | { | ||
200 | if( !isFilled( nPos ) ) return NULL; | ||
201 | if( hFunc->cmpIDs( id, aTable[nPos].id ) && | ||
202 | aTable[nPos].bDeleted == false ) | ||
203 | { | ||
204 | if( nSkip == 0 ) | ||
205 | { | ||
206 | return aTable[nPos].data; | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | nSkip--; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | void *HashTable::getFirstItemPos() | ||
219 | { | ||
220 | HashPos *pos = new HashPos; | ||
221 | return pos; | ||
222 | } | ||
223 | |||
224 | const void *HashTable::getItemData( void *xPos ) | ||
225 | { | ||
226 | return aTable[((HashPos *)xPos)->nPos].data; | ||
227 | } | ||
228 | |||
229 | const void *HashTable::getItemID( void *xPos ) | ||
230 | { | ||
231 | return aTable[((HashPos *)xPos)->nPos].id; | ||
232 | } | ||
233 | |||
234 | void *HashTable::getNextItemPos( void *xPos ) | ||
235 | { | ||
236 | HashPos *pos = (HashPos *)xPos; | ||
237 | if( pos->bStarted == false ) | ||
238 | { | ||
239 | pos->bStarted = true; | ||
240 | pos->nPos = 0; | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | pos->nPos++; | ||
245 | } | ||
246 | if( pos->nPos < nTableSize ) | ||
247 | { | ||
248 | for( ; pos->nPos < nTableSize; pos->nPos++ ) | ||
249 | { | ||
250 | if( isFilled( pos->nPos ) && | ||
251 | aTable[pos->nPos].bDeleted == false ) | ||
252 | { | ||
253 | return xPos; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | delete pos; | ||
259 | |||
260 | return NULL; | ||
261 | } | ||
262 | |||
263 | // Big-O sqrt(n) | ||
264 | // Change this to be erethpothynies table with a storage | ||
265 | // lookup later on. | ||
266 | bool HashTable::isPrime (int num) | ||
267 | { | ||
268 | if (num == 2) // the only even prime | ||
269 | return true; | ||
270 | else if (num % 2 == 0) // other even numbers are composite | ||
271 | return false; | ||
272 | else | ||
273 | { | ||
274 | //bool prime = true; | ||
275 | int divisor = 3; | ||
276 | int upperLimit = static_cast<int>(sqrt(num) + 1); | ||
277 | while (divisor <= upperLimit) | ||
278 | { | ||
279 | if (num % divisor == 0) | ||
280 | return false; | ||
281 | // prime = false; | ||
282 | divisor +=2; | ||
283 | } | ||
284 | return true; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | // Big-O n^(3/2) | ||
289 | int HashTable::nextPrime( int base ) | ||
290 | { | ||
291 | int nPrime; | ||
292 | for( nPrime = base; isPrime( nPrime ) == false; nPrime++ ); | ||
293 | return nPrime; | ||
294 | } | ||
295 | |||
296 | unsigned long int HashTable::getCapacity() | ||
297 | { | ||
298 | return nTableSize; | ||
299 | } | ||
300 | |||
301 | unsigned long int HashTable::getSize() | ||
302 | { | ||
303 | return nSize; | ||
304 | } | ||
305 | |||
306 | double HashTable::getLoad() | ||
307 | { | ||
308 | return (double)(nFilled)/(double)(nTableSize); | ||
309 | } | ||
310 | |||
311 | const void *HashTable::operator[](const void *id) | ||
312 | { | ||
313 | return get( id ); | ||
314 | } | ||
315 | |||
316 | bool HashTable::del( const void *id, int nSkip ) | ||
317 | { | ||
318 | unsigned long int nPos = hFunc->hash( id )%nTableSize; | ||
319 | |||
320 | for( unsigned long int j=0; j < 32; nPos = (nPos+(1<<j))%nTableSize, j++ ) | ||
321 | { | ||
322 | if( !isFilled( nPos ) ) return false; | ||
323 | if( hFunc->cmpIDs( id, aTable[nPos].id ) && | ||
324 | aTable[nPos].bDeleted == false ) | ||
325 | { | ||
326 | if( nSkip == 0 ) | ||
327 | { | ||
328 | aTable[nPos].bDeleted = true; | ||
329 | // aTable[nPos]. | ||
330 | nSize--; | ||
331 | #ifdef HASH_DEBUG_VIS | ||
332 | printDebugLine( (const char *)id ); | ||
333 | #endif | ||
334 | return true; | ||
335 | } | ||
336 | else | ||
337 | { | ||
338 | nSkip--; | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
343 | return false; | ||
344 | } | ||
345 | |||
diff --git a/src/hashtable.h b/src/hashtable.h new file mode 100644 index 0000000..d14be71 --- /dev/null +++ b/src/hashtable.h | |||
@@ -0,0 +1,299 @@ | |||
1 | /**\hashtable.h | ||
2 | * Describes the HashFunction, HashFunctionString, and HashTable classes. It | ||
3 | * was just easier to put them all in one set of files. | ||
4 | *@author Mike Buland | ||
5 | */ | ||
6 | |||
7 | #ifndef HASH_TABLE_H | ||
8 | #define HASH_TABLE_H | ||
9 | |||
10 | //Uncomment this line to see a cool text-mode visualization of what's going on | ||
11 | //#define HASH_DEBUG_VIS 1 | ||
12 | |||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <ctype.h> | ||
16 | |||
17 | #include "hashfunction.h" | ||
18 | |||
19 | /** | ||
20 | * A simple yet flexable hash-table. This uses several tricks to help ensure | ||
21 | * that the table is always running at maximum efficiency. You no longer have | ||
22 | * to specify a "danger fill level" when more space is needed a rehash is | ||
23 | * automatically trigered. Deleting elements is fully supported, as well as | ||
24 | * duplicate elements. To work with and allow duplicates simple construct your | ||
25 | * HashTable the way you normally would, but when deleting or getting elements | ||
26 | * you can specify a skip value. This effectively allows you to treat elements | ||
27 | * with duplicate ID's as though they were in a zero-based array. The first | ||
28 | * element inserted with a given ID would be at skip zero, the next at skip 1 | ||
29 | * and so on. This allows you to quickly search for elements with duplicate | ||
30 | * names, just stop when you get a null for a skip number, i.e. | ||
31 | * <pre> | ||
32 | * for( int j = 0;; j++ ) | ||
33 | * { | ||
34 | * void *pData = hash.get( myID, j ); | ||
35 | * if( !pData ) break; | ||
36 | * // Do something interesting with pData | ||
37 | * } | ||
38 | * </pre> | ||
39 | * There are new features in this HashTable that also allow for memory saving | ||
40 | * when dealing with systems where many elements are being deleted from the | ||
41 | * table. In those cases the elements deleted cannot be simply deleted, instead | ||
42 | * they have to be marked as deleted and hidden from the user, but maintained in | ||
43 | * the table so that future hashing operations don't fail. When rehashing | ||
44 | * occurs all elements marked as deleted are quietly removed. In these cases, | ||
45 | * if the number of deleted items would free enough space in the table for the | ||
46 | * table to be used efficiently without resizing, it is left the same size and | ||
47 | * rehashing is performed effectively in place, allowing the deleted items to | ||
48 | * be removed. | ||
49 | * <br> | ||
50 | * For info on adding new hashing algorithms, please see the HashFunction class. | ||
51 | *@author Mike Buland | ||
52 | *@todo Fix probing for tables that allow duplicates, and delete an item, then | ||
53 | * insert an item with the same name. | ||
54 | */ | ||
55 | class HashTable | ||
56 | { | ||
57 | public: | ||
58 | /** Constructs a hash table. | ||
59 | *@param hNewFunc A pointer to a hashfunction class to use. If this is | ||
60 | * null the default general string type will be used. | ||
61 | *@param nInitSize The initial size of the hashtable. | ||
62 | *@param bAllowDupes Setting this value to true allows the system to | ||
63 | * insert more than one copy of any given key. This can be tricky, and | ||
64 | * will require you to use the nSkip parameter on the get function. | ||
65 | */ | ||
66 | HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes=false ); | ||
67 | |||
68 | /** | ||
69 | * Destroys the hashtable, cleaning up all internal storage, but not stored | ||
70 | * elements. Also deletes the HashFunction passed in in the constructor. | ||
71 | */ | ||
72 | ~HashTable(); | ||
73 | |||
74 | /** Inserts an item into the hashtable. This function will trigger a | ||
75 | * rehash if adding another item would force the table's load factor over | ||
76 | * the danger level. | ||
77 | *@param id used to find the data later. | ||
78 | *@param data The data item to insert into the table with the identifier | ||
79 | * id | ||
80 | *@returns True if insertion was successfull, and false if it failed. | ||
81 | */ | ||
82 | bool insert( const void *id, const void *data ); | ||
83 | |||
84 | /** Gets an item in the hashtable based on the id of that item. If there | ||
85 | * is more than one item with the same id you can use the nSkip parameter | ||
86 | * to access all of them. | ||
87 | *@param id The id of the item you're trying to find. | ||
88 | *@param nSkip The number of items with that id to skip before returning | ||
89 | * with the requested item. | ||
90 | *@returns A pointer to the data stored at the given id. | ||
91 | */ | ||
92 | const void *get( const void *id, unsigned long int nSkip=0 ); | ||
93 | |||
94 | /** Gets the total capacity of the hashtable. This is actually the number | ||
95 | * of total positions available inside the hashtable at the moment. This | ||
96 | * will change when the hashtable's load exceeds the danger level. | ||
97 | * Please note that this is NOT the actual amount of space available. | ||
98 | * In reality you can only access about 45-50 percent of that space. | ||
99 | *@returns The total capacity. | ||
100 | */ | ||
101 | unsigned long int getCapacity(); | ||
102 | |||
103 | /** Gets the number of filled in items in the hash table. This is roughly | ||
104 | * equivelent to the getSize function assosiated with the Lists. | ||
105 | *@returns The number of filled in items in the hash table. | ||
106 | */ | ||
107 | unsigned long int getSize(); | ||
108 | |||
109 | /** Gets the load (percentage) of filled in items in the table. This is | ||
110 | * technically the size divided by the capacity, but is definately usefull | ||
111 | * since it's required to check if it's time to rehash. | ||
112 | *@returns The table load in the range 0.0 to 1.0 | ||
113 | */ | ||
114 | double getLoad(); | ||
115 | |||
116 | /** Sets up an xPos object for use indexing the items in the table. Call | ||
117 | * this first and follow the directions for getNextItemPos below to | ||
118 | * iterate through every item in the table, while avoiding the empty | ||
119 | * spaces. | ||
120 | *@returns A pointer to a xPos object telling the hashtable where to find | ||
121 | * the item you're looking at. | ||
122 | */ | ||
123 | void *getFirstItemPos(); | ||
124 | |||
125 | /** Get the item's data that is being pointed to by xPos. This is only | ||
126 | * valid after xPos was created using getFirstItemPos and getNextItemPos | ||
127 | * was called at least once. | ||
128 | *@param xPos supplied by getFirstItemPos. | ||
129 | *@returns The key value that was used to insert the data into the table. | ||
130 | */ | ||
131 | const void *getItemData( void *xPos ); | ||
132 | |||
133 | /** Get the item's ID that is being pointed to by xPos. This is only | ||
134 | * valid after xPos was created using getFirstItemPos and getNextItemPos | ||
135 | * was called at least once. | ||
136 | *@param xPos supplied by getFirstItemPos. | ||
137 | *@returns The key value that was used to insert the data into the table. | ||
138 | */ | ||
139 | const void *getItemID( void *xPos ); | ||
140 | |||
141 | /** Used for iterating through a hash table sequentially. This will | ||
142 | * update the xPos pointer to point to the next time, all ready to | ||
143 | * be accessed with getItemID and getItemData. This must be called at | ||
144 | * least once before xPos is meaningful, and will return a NULL when it | ||
145 | * has reached the last item. | ||
146 | *@param xPos This must be an object created by a call to the function | ||
147 | * getFirstItemPos, and is only meaningful to the internal routines. | ||
148 | * Aborting a call in the middle (not running to the end of the table) | ||
149 | * may result in a memory leak at the moment. | ||
150 | *@returns xPos if still iterating through the list, otherwise it will | ||
151 | * return NULL when the end has been reached and the xPos variable has | ||
152 | * been deleted. | ||
153 | */ | ||
154 | void *getNextItemPos( void *xPos ); | ||
155 | |||
156 | /** A helpful operator to make accessing items easier. Please note that | ||
157 | * this simply returns a pointer to the data stored internally, and cannot | ||
158 | * be used like the STL operator to store new data, use insert for that. | ||
159 | *@param id The identifier used to store the requested item. | ||
160 | *@returns The data value assosiated with the given id, or NULL if it | ||
161 | * wasn't found in the table. | ||
162 | */ | ||
163 | const void *operator[](const void *id); | ||
164 | |||
165 | /** | ||
166 | * Delete the specified item from the hashtable. This actually keeps the | ||
167 | * data and marks it deleted. For all intents and purposes to the user it | ||
168 | * is deleted, except that the space is still used until a rehash is forced. | ||
169 | * This means that in hashtables where elements are being inserted and | ||
170 | * deleted frequently you may run into a higher rate of expansion. | ||
171 | *@param id The ID to delete. | ||
172 | *@param nSkip The number of similar id's to skip before deleting in a | ||
173 | * hashtable that allows duplicates. | ||
174 | *@returns True if the element was found and deleted, false otherwise. | ||
175 | */ | ||
176 | bool del( const void *id, int nSkip=0 ); | ||
177 | |||
178 | private: | ||
179 | /** | ||
180 | * Contains info related to a position in the hashtable. Used for | ||
181 | * searching through hashtables one item at a time, in order. This class | ||
182 | * should never be created by anything but a HashTable, and should never | ||
183 | * be referenced directly. Instead the hashtable returns a void pointer, | ||
184 | * which is what should be passed back in next time you use a search | ||
185 | * function. Always finish a search, since the object is deleted at the | ||
186 | * end of the search. | ||
187 | *@author Mike Buland | ||
188 | */ | ||
189 | class HashPos | ||
190 | { | ||
191 | public: | ||
192 | /** Create a blank HashPos. */ | ||
193 | HashPos() { bStarted=false; nPos = 0; }; | ||
194 | /** Has the search been started? */ | ||
195 | bool bStarted; | ||
196 | /** The position (index) into the backend storage structure. */ | ||
197 | unsigned long int nPos; | ||
198 | }; | ||
199 | |||
200 | /** | ||
201 | * All data related to a single element in the hashtable. This should | ||
202 | * really only be used and manipulated by the HashTable itself. | ||
203 | *@author Mike Buland | ||
204 | */ | ||
205 | typedef struct HashNode | ||
206 | { | ||
207 | public: | ||
208 | /** Create a new, empty HashNode. */ | ||
209 | HashNode() { id = NULL; data = NULL; bDeleted = false; }; | ||
210 | /** A pointer to the original ID that was used to key the data. */ | ||
211 | const void *id; | ||
212 | /** A pointer to the data stored along with the above ID. */ | ||
213 | const void *data; | ||
214 | /** Weather or not this data should really...exist */ | ||
215 | bool bDeleted; | ||
216 | } HashNode; | ||
217 | |||
218 | private: | ||
219 | /** | ||
220 | * Just sets the values in the element to some friendly values. | ||
221 | *@param newID The new ID to store. | ||
222 | *@param newData The new Data to store. | ||
223 | */ | ||
224 | void set( int j, const void *newID, const void *newData ); | ||
225 | /** | ||
226 | * Tells you if the node is filled or not. | ||
227 | *@returns True=an ID has been stored here, False=no ID. | ||
228 | */ | ||
229 | bool isFilled( int j ); | ||
230 | /** | ||
231 | * This actually resizes, but since every resize requires a reHash to go | ||
232 | * along with it, that's the name. This actually creates a new buffer for | ||
233 | * all of the contained data and then pulls every old element that was in | ||
234 | * the old table out and performs the hashing placement calculations again. | ||
235 | * This function skips all data that was marked as deleted, so at this | ||
236 | * point it really will be. | ||
237 | *@param nNewSize The new size to set the table to while re-hashing. | ||
238 | *@returns True if the operation was successful, false otherwise. | ||
239 | */ | ||
240 | bool reHash( unsigned long int nNewSize ); | ||
241 | |||
242 | /** | ||
243 | * Helper function to allocate a new table. Really just does the memory | ||
244 | * allocation. | ||
245 | *@param nNewSize The size of the table to generate. | ||
246 | *@returns A new, blank array of HashNode objects the size you specified. | ||
247 | */ | ||
248 | HashNode *newTable( unsigned long int nNewSize ); | ||
249 | |||
250 | /** | ||
251 | * This function is used once an actual hash code is obtained. nStart is | ||
252 | * the given hash code, which is then wrapped to the size of the table. If | ||
253 | * there is data at that location, tests are performed to see if it's the | ||
254 | * right one. If it is, then it is returned, otherwise a series of further | ||
255 | * tests based on a 2^n search pattern is performed. The position of the | ||
256 | * requested data in the back-end storage is returned if found, otherwise | ||
257 | * another less useful value is returned... | ||
258 | *@param nStart The initial hashcode of the ID testing for. | ||
259 | *@param id A pointer to the id that is being searched for. | ||
260 | *@returns The real location of the data requested. | ||
261 | */ | ||
262 | unsigned long int probe( unsigned long int nStart, const void *id ); | ||
263 | |||
264 | /** | ||
265 | * Simple helper function to determine if a number is prime or not. | ||
266 | * This function runs in sqrt(n) time. | ||
267 | *@param num Number to test for prime-hood. | ||
268 | *@returns True if the number is prime, false otherwise. | ||
269 | */ | ||
270 | bool isPrime( int num ); | ||
271 | |||
272 | /** | ||
273 | * Given any number, this function finds the first number after it that is | ||
274 | * prime. Since this number is a multiple internally it's rare that the | ||
275 | * starting number would be prime. | ||
276 | *@param base The number to start the prime search on. | ||
277 | *@returns The first prime after the number given. | ||
278 | */ | ||
279 | int nextPrime( int base ); | ||
280 | |||
281 | #ifdef HASH_DEBUG_VIS | ||
282 | void printDebugLine( const char *exData ); | ||
283 | #endif | ||
284 | |||
285 | /** A pointer to the HashFunction subclass instance to use. */ | ||
286 | HashFunction *hFunc; | ||
287 | /** The complete array of HashNode objects to store data in. */ | ||
288 | HashNode *aTable; | ||
289 | /** The actual size of the table, not how many elements are in it. */ | ||
290 | unsigned long int nTableSize; | ||
291 | /** The number of elements that are in the table. */ | ||
292 | unsigned long int nSize; | ||
293 | /** The number of elements that are unavailable now. */ | ||
294 | unsigned long int nFilled; | ||
295 | /** Allow duplicate ID's in the table. */ | ||
296 | bool bAllowDupes; | ||
297 | }; | ||
298 | |||
299 | #endif | ||
diff --git a/src/http.cpp b/src/http.cpp new file mode 100644 index 0000000..11950b7 --- /dev/null +++ b/src/http.cpp | |||
@@ -0,0 +1,371 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "http.h" | ||
4 | #include "hashfunctionstring.h" | ||
5 | |||
6 | Http::Http( Connection *pConnection ) : hReqHeader( new HashFunctionString(), 100 ) | ||
7 | { | ||
8 | pCon = pConnection; | ||
9 | nParseState = parseInit; | ||
10 | } | ||
11 | |||
12 | Http::~Http() | ||
13 | { | ||
14 | for( int j = 0; j < lStrings.getSize(); j++ ) | ||
15 | { | ||
16 | delete (std::string *)lStrings[j]; | ||
17 | } | ||
18 | } | ||
19 | |||
20 | bool Http::parseRequest() | ||
21 | { | ||
22 | for(;;) | ||
23 | { | ||
24 | pCon->readInput(); | ||
25 | switch( nParseState ) | ||
26 | { | ||
27 | case parseInit: | ||
28 | { | ||
29 | int nLen = pCon->scanInputFor( CR ); | ||
30 | if( nLen == -1 ) | ||
31 | { | ||
32 | return false; | ||
33 | } | ||
34 | else | ||
35 | { | ||
36 | nReqType = getRequestType( pCon->getInput() ); | ||
37 | pCon->usedInput( pCon->scanInputFor(' ')+1 ); | ||
38 | |||
39 | nLen = pCon->scanInputFor(' '); | ||
40 | sReqURI.append( pCon->getInput(), nLen ); | ||
41 | pCon->usedInput( nLen+1 ); | ||
42 | |||
43 | if( !strncmp( pCon->getInput(), "HTTP/", 5 ) ) | ||
44 | { | ||
45 | char mbuf[2]={'\0','\0'}; | ||
46 | unsigned char major, minor; | ||
47 | |||
48 | pCon->usedInput( 5 ); | ||
49 | mbuf[0] = pCon->getInput()[0]; | ||
50 | major = (unsigned char)atoi(mbuf); | ||
51 | mbuf[0] = pCon->getInput()[2]; | ||
52 | minor = (unsigned char)atoi(mbuf); | ||
53 | setRequestVersion( major, minor ); | ||
54 | if( checkRequestVer() ) | ||
55 | { | ||
56 | nParseState = parseHeader; | ||
57 | } | ||
58 | else | ||
59 | { | ||
60 | setResponseStatus( statusHTTPVersionNotSupported ); | ||
61 | printf("Verson not supported.\n"); | ||
62 | return true; | ||
63 | } | ||
64 | |||
65 | pCon->usedInput( 5 ); | ||
66 | } | ||
67 | else | ||
68 | { | ||
69 | setResponseStatus( statusBadRequest ); | ||
70 | } | ||
71 | |||
72 | //return false; | ||
73 | } | ||
74 | } | ||
75 | break; | ||
76 | |||
77 | case parseHeader: | ||
78 | { | ||
79 | int nLen = pCon->scanInputFor( CR ); | ||
80 | if( nLen == -1 ) | ||
81 | { | ||
82 | return false; | ||
83 | } | ||
84 | else if( nLen == 0 ) | ||
85 | { | ||
86 | // We've got our double-newline, time for content. | ||
87 | pCon->usedInput( 2 ); | ||
88 | setResponseStatus( statusOK ); | ||
89 | return true; | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | nLen = pCon->scanInputFor(':'); | ||
94 | if( nLen == -1 ) | ||
95 | { | ||
96 | printf("No colon? what are you trying to pull?\n"); | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | std::string *pName = new std::string( pCon->getInput(), nLen ); | ||
101 | lStrings.append( pName ); | ||
102 | pCon->usedInput( nLen+1 ); | ||
103 | |||
104 | nLen = pCon->scanInputFor( CR ); | ||
105 | std::string *pValue = convSpaceString( pCon->getInput(), nLen ); | ||
106 | lStrings.append( pValue ); | ||
107 | pCon->usedInput( nLen+2 ); | ||
108 | |||
109 | hReqHeader.insert( | ||
110 | pName->c_str(), | ||
111 | pValue->c_str() | ||
112 | ); | ||
113 | |||
114 | printf("::%s = \"%s\"\n", | ||
115 | pName->c_str(), | ||
116 | pValue->c_str() | ||
117 | ); | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | break; | ||
122 | |||
123 | case parseFinished: | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | bool Http::buildResponse( short nResponseCode, const char *sResponse ) | ||
130 | { | ||
131 | if( nResponseCode > 0 ) | ||
132 | { | ||
133 | nResStatus = nResponseCode; | ||
134 | } | ||
135 | |||
136 | if( sResponse == NULL ) | ||
137 | { | ||
138 | sResStatusStr = "uh yeah"; | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | sResStatusStr = sResponse; | ||
143 | } | ||
144 | |||
145 | time_t curTime; | ||
146 | time( &curTime ); | ||
147 | gmtime_r( &curTime, &tResTime ); | ||
148 | |||
149 | sServerStr = "YFHttp/0.0.1"; | ||
150 | bResPersistant = false; | ||
151 | |||
152 | //char buf[30]; | ||
153 | //strftime( buf, 30, "%a, %d %b %Y %H:%M:%S GMT", &tResponseTime ); | ||
154 | |||
155 | return true; | ||
156 | } | ||
157 | |||
158 | bool Http::sendResponse() | ||
159 | { | ||
160 | char buf[256]; | ||
161 | |||
162 | sprintf( buf, "HTTP/1.1 %d %s\r\n", nResStatus, sResStatusStr.c_str() ); | ||
163 | pCon->appendOutput( buf ); | ||
164 | |||
165 | strftime( buf, 256, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &tResTime ); | ||
166 | pCon->appendOutput( buf ); | ||
167 | |||
168 | sprintf( buf, "Server: %s\r\n", sServerStr.c_str() ); | ||
169 | pCon->appendOutput( buf ); | ||
170 | |||
171 | if( bResPersistant ) | ||
172 | { | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | pCon->appendOutput("Connection: close\r\n"); | ||
177 | } | ||
178 | |||
179 | sprintf( buf, "Content-Type: %s\r\n", sResMime.c_str() ); | ||
180 | pCon->appendOutput( buf ); | ||
181 | |||
182 | sprintf( buf, "Content-Length: %d\r\n", sResContent.size() ); | ||
183 | pCon->appendOutput( buf ); | ||
184 | |||
185 | pCon->appendOutput("\r\n"); | ||
186 | |||
187 | pCon->appendOutput( sResContent.c_str(), sResContent.size() ); | ||
188 | |||
189 | return true; | ||
190 | } | ||
191 | |||
192 | void Http::setResponsePersistant( bool bPersistant ) | ||
193 | { | ||
194 | bResPersistant = bPersistant; | ||
195 | } | ||
196 | |||
197 | void Http::setResponseContent( const char *sMime, const char *sContent, int nLen ) | ||
198 | { | ||
199 | sResMime = sMime; | ||
200 | sResContent.erase(); | ||
201 | sResContent.append( sContent, nLen ); | ||
202 | } | ||
203 | |||
204 | std::string *Http::convSpaceString( const char *sStr, int nLen ) | ||
205 | { | ||
206 | int nNewLen = 0; | ||
207 | bool bStart = true; | ||
208 | bool bSpace = false; | ||
209 | |||
210 | for( int j = 0; j < nLen; j++ ) | ||
211 | { | ||
212 | if( sStr[j] == ' ' || sStr[j] == '\t' ) | ||
213 | { | ||
214 | if( bStart ) | ||
215 | { | ||
216 | } | ||
217 | else if( bSpace == false ) | ||
218 | { | ||
219 | bSpace = true; | ||
220 | nNewLen++; | ||
221 | } | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | bStart = false; | ||
226 | bSpace = false; | ||
227 | nNewLen++; | ||
228 | } | ||
229 | } | ||
230 | if( bSpace ) | ||
231 | { | ||
232 | nNewLen--; | ||
233 | } | ||
234 | |||
235 | std::string *pSStr = new std::string; | ||
236 | //char *pStr = pSStr->c_str(); | ||
237 | nNewLen = 0; | ||
238 | bStart = true; | ||
239 | bSpace = false; | ||
240 | |||
241 | for( int j = 0; j < nLen; j++ ) | ||
242 | { | ||
243 | if( sStr[j] == ' ' || sStr[j] == '\t' ) | ||
244 | { | ||
245 | if( bStart ) | ||
246 | { | ||
247 | } | ||
248 | else if( bSpace == false ) | ||
249 | { | ||
250 | bSpace = true; | ||
251 | *pSStr += ' '; | ||
252 | //pStr[nNewLen++] = ' '; | ||
253 | } | ||
254 | } | ||
255 | else | ||
256 | { | ||
257 | bStart = false; | ||
258 | bSpace = false; | ||
259 | *pSStr += sStr[j]; | ||
260 | //pStr[nNewLen++] = sStr[j]; | ||
261 | } | ||
262 | } | ||
263 | if( bSpace == true ) | ||
264 | { | ||
265 | nNewLen--; | ||
266 | // pStr[nNewLen] = '\0'; | ||
267 | } | ||
268 | |||
269 | return pSStr; | ||
270 | } | ||
271 | |||
272 | const char *Http::getRequestURI() | ||
273 | { | ||
274 | return sReqURI.c_str(); | ||
275 | } | ||
276 | |||
277 | short Http::getRequestType( const char *sType ) | ||
278 | { | ||
279 | if( !strncmp( sType, "OPTIONS", 7 ) ) | ||
280 | { | ||
281 | return reqOptions; | ||
282 | } | ||
283 | else if( !strncmp( sType, "GET", 3 ) ) | ||
284 | { | ||
285 | return reqGet; | ||
286 | } | ||
287 | else if( !strncmp( sType, "HEAD", 4 ) ) | ||
288 | { | ||
289 | return reqHead; | ||
290 | } | ||
291 | else if( !strncmp( sType, "POST", 4 ) ) | ||
292 | { | ||
293 | return reqPost; | ||
294 | } | ||
295 | else if( !strncmp( sType, "PUT", 3 ) ) | ||
296 | { | ||
297 | return reqPut; | ||
298 | } | ||
299 | else if( !strncmp( sType, "DELETE", 6 ) ) | ||
300 | { | ||
301 | return reqDelete; | ||
302 | } | ||
303 | else if( !strncmp( sType, "TRACE", 5 ) ) | ||
304 | { | ||
305 | return reqTrace; | ||
306 | } | ||
307 | else if( !strncmp( sType, "CONNECT", 7 ) ) | ||
308 | { | ||
309 | return reqConnect; | ||
310 | } | ||
311 | else | ||
312 | { | ||
313 | printf(" Uh oh, extension!\n"); | ||
314 | return reqExtension; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | const char *Http::getRequestType( short nType ) | ||
319 | { | ||
320 | switch( nType ) | ||
321 | { | ||
322 | case reqOptions: return "OPTIONS"; | ||
323 | case reqGet: return "GET"; | ||
324 | case reqHead: return "HEAD"; | ||
325 | case reqPost: return "POST"; | ||
326 | case reqPut: return "PUT"; | ||
327 | case reqDelete: return "DELETE"; | ||
328 | case reqTrace: return "TRACE"; | ||
329 | case reqConnect: return "CONNECT"; | ||
330 | case reqExtension: return "EXTENSION"; | ||
331 | default: return "INVALID VALUE"; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | short Http::getRequestType() | ||
336 | { | ||
337 | return nReqType; | ||
338 | } | ||
339 | |||
340 | const char *Http::getRequestTypeStr() | ||
341 | { | ||
342 | return getRequestType( nReqType ); | ||
343 | } | ||
344 | |||
345 | void Http::setResponseStatus( short nStatus ) | ||
346 | { | ||
347 | nResStatus = nStatus; | ||
348 | } | ||
349 | |||
350 | void Http::setRequestVersion( unsigned char nMajor, unsigned char nMinor ) | ||
351 | { | ||
352 | cReqVersion = (nMajor<<4)|nMinor; | ||
353 | } | ||
354 | |||
355 | unsigned char Http::getRequestMinorVer() | ||
356 | { | ||
357 | return cReqVersion&0x0F; | ||
358 | } | ||
359 | |||
360 | unsigned char Http::getRequestMajorVer() | ||
361 | { | ||
362 | return cReqVersion>>4; | ||
363 | } | ||
364 | |||
365 | bool Http::checkRequestVer() | ||
366 | { | ||
367 | if( cReqVersion == HTTP11 ) | ||
368 | return true; | ||
369 | return false; | ||
370 | } | ||
371 | |||
diff --git a/src/http.h b/src/http.h new file mode 100644 index 0000000..4ee4470 --- /dev/null +++ b/src/http.h | |||
@@ -0,0 +1,271 @@ | |||
1 | /**\file http.h | ||
2 | * Describe a Hyper Text Transfer Protocol processor. This class will allow | ||
3 | * any program to act as either an HTTP server, client, or both. It contains | ||
4 | * a number of additional helpers and subclasses. | ||
5 | *@author Mike Buland | ||
6 | */ | ||
7 | |||
8 | #ifndef HTTP_H | ||
9 | #define HTTP_H | ||
10 | |||
11 | #include <iostream> | ||
12 | #include "connection.h" | ||
13 | #include "linkedlist.h" | ||
14 | #include "hashtable.h" | ||
15 | |||
16 | #define CR '\r' /**< The ASCII value of a Carrage Return */ | ||
17 | #define LF '\n' /**< The ASCII value of a Line Feed */ | ||
18 | #define CRLF CR LF /**< Combo of CR+LF for use in http */ | ||
19 | |||
20 | /** | ||
21 | * Macro to create combined http version codes. This just makes processing a | ||
22 | * little bit faster for the most part. | ||
23 | *@param maj Major version number, between 0 and 15 | ||
24 | *@param min Minor version number, between 0 and 15 | ||
25 | *@returns A one byte combined version number suitable for use in switches. | ||
26 | */ | ||
27 | #define HTTPVER( maj, min ) ((maj<<4)|(min)) | ||
28 | |||
29 | #define HTTP10 HTTPVER( 1, 0 ) /**< Combined version code for http 1.0 */ | ||
30 | #define HTTP11 HTTPVER( 1, 1 ) /**< Combined version code for http 1.1 */ | ||
31 | |||
32 | /** | ||
33 | * This is the master HTTP processing class. One instance handles one | ||
34 | * transaction, in the future a different mechanism may be thought up, but for | ||
35 | * now this means that you must create multiple objects to handle a single | ||
36 | * connection that contains multiple requests. | ||
37 | * In the constructor the Http class is given a connection object. This object | ||
38 | * should already be initialized and connected to whatever socket it wants to | ||
39 | * be sending and receiving data to and from. Once that's done you can call | ||
40 | * parseRequest if you're acting as a server, or a variety of buildRequest | ||
41 | * functions to create and send a request if you're a client. | ||
42 | * Please note that this class does not provide any HTTP or extended format | ||
43 | * processing systems, but will allow for mime types tables to be registered. | ||
44 | *@author Mike Buland | ||
45 | */ | ||
46 | class Http | ||
47 | { | ||
48 | public: | ||
49 | /** | ||
50 | * Create an Http object tied to an existing connection object. | ||
51 | *@param pConnection The live connection object to deal with. | ||
52 | */ | ||
53 | Http( Connection *pConnection ); | ||
54 | |||
55 | /** | ||
56 | * Standard Deconstructor. | ||
57 | */ | ||
58 | ~Http(); | ||
59 | |||
60 | /** | ||
61 | * Perform all parsing needed to figure out what an HTTP client wants from | ||
62 | * us. This will setup a number of properties in the Http object itself | ||
63 | * and has the possibility of setting one or more response states initially. | ||
64 | * These states should be checked for immediately after parsing to see if | ||
65 | * an appropriate error message should be generated. These errors can | ||
66 | * include issues with protocol, data formats, or unknown versions of the | ||
67 | * protocol. | ||
68 | *@returns True means that all processing is finished, false means that | ||
69 | * the parseRequest function should be called again when more data is | ||
70 | * ready. A return value of true does not indicate success, only that | ||
71 | * processing is finished, the getResponseStatus function should be called | ||
72 | * to see what status was set in the parse routine. A 200 indicates that | ||
73 | * as far as the parser is concerned, everything when smoothly. Otherwise | ||
74 | * it's your responsibility to build the appropriate error response body | ||
75 | * (like an html file) and send it as the response. | ||
76 | */ | ||
77 | bool parseRequest(); | ||
78 | |||
79 | /** | ||
80 | * Get a request type's internal Http object id based on the string | ||
81 | * representation. These can be any HTTP/1.1 standard request type. | ||
82 | *@param sType The string that should be checked for type. This is in all | ||
83 | * caps, just like if it came from the HTTP client, which is most often | ||
84 | * the case. | ||
85 | *@returns The numerical ID of the given request type. Please note that | ||
86 | * HTTP/1.1 standard specifies that any string is valid here as long as | ||
87 | * the non-basic string is a request type understood by the serving | ||
88 | * software. This means that anything that is non-standard will return | ||
89 | * a type reqExtension and not an error. This is not a mistake. | ||
90 | */ | ||
91 | short getRequestType( const char *sType ); | ||
92 | |||
93 | /** | ||
94 | * Get the string representation of an Http object request type integer ID. | ||
95 | * This is used mainly for debugging to be sure the system has what we | ||
96 | * think it has. | ||
97 | *@param nType The integer ID of the request type to process. | ||
98 | *@returns The HTTP/1.1 string representation of that Http object ID code. | ||
99 | */ | ||
100 | const char *getRequestType( short nType ); | ||
101 | |||
102 | /** | ||
103 | * Returns the Http object request type ID code that is stored in the | ||
104 | * object by either the parseRequest function or use of the buildRequest | ||
105 | * functions. | ||
106 | *@returns The ID of the request type stored in the object. | ||
107 | */ | ||
108 | short getRequestType(); | ||
109 | |||
110 | /** | ||
111 | * Same as getRequestType, only returns the string representation. | ||
112 | *@returns The string representation of the request type ID stored in the | ||
113 | * object. | ||
114 | */ | ||
115 | const char *getRequestTypeStr(); | ||
116 | |||
117 | /** | ||
118 | * Sets the version of the request used by the system. This will be used | ||
119 | * by parse request, but is also part of the buildRequest tool functions. | ||
120 | *@param nMajor The major version number. | ||
121 | *@param nMinor The minor version number. | ||
122 | */ | ||
123 | void setRequestVersion( unsigned char nMajor, unsigned char nMinor ); | ||
124 | |||
125 | /** | ||
126 | * Gets the major version number of the protocol used/to be used in this | ||
127 | * request. | ||
128 | *@returns The major version number of the request protocol. | ||
129 | */ | ||
130 | unsigned char getRequestMinorVer(); | ||
131 | |||
132 | /** | ||
133 | * Gets the minor version number of the protocol used/to be used in this | ||
134 | * request. | ||
135 | *@returns The minor version number of the request protocol. | ||
136 | */ | ||
137 | unsigned char getRequestMajorVer(); | ||
138 | |||
139 | /** | ||
140 | * Checks the stored request version against an internal table of supported | ||
141 | * protocol versions. | ||
142 | *@returns True if the protocol version is supported, false otherwise. | ||
143 | */ | ||
144 | bool checkRequestVer(); | ||
145 | |||
146 | /** | ||
147 | * Converts an arbitrary string to a new string object with space saving | ||
148 | * operations performed ala the HTTP/1.1 specs. All leading and trailing | ||
149 | * whitespace is stripped, and all whitespace within the string is reduced | ||
150 | * to a single space char. | ||
151 | *@param sStr A pointer to the string data to process. | ||
152 | *@param nLen The length of the string to process. Since this function is | ||
153 | * often called on stream data, there is no null terminator where we need | ||
154 | * one. This is here for convinience so the data doesn't need to be hacked | ||
155 | * up or moved to an intermediate buffer. | ||
156 | *@returns A new string that may well be shorter than the original but that | ||
157 | * will have the same value as far as the HTTP/1.1 specs are concerned. | ||
158 | */ | ||
159 | std::string *convSpaceString( const char *sStr, int nLen ); | ||
160 | |||
161 | /** | ||
162 | * Gets a string pointer to the URI that was/is being requested. This can | ||
163 | * be any RFC standard URI, with or without protocol and domain. | ||
164 | *@returns A pointer to the URI that was/is being requested. | ||
165 | */ | ||
166 | const char *getRequestURI(); | ||
167 | |||
168 | /** | ||
169 | * Set a new response status. This status can be anything that the HTTP | ||
170 | * specs allow. Other values are allowed as well, but beware, not all | ||
171 | * servers/clients will accept values that are not in the tables in this | ||
172 | * class. | ||
173 | *@param nStatus The status to set. | ||
174 | */ | ||
175 | void setResponseStatus( short nStatus ); | ||
176 | |||
177 | bool buildResponse( short nResponseCode=-1, const char *sResponse=NULL ); | ||
178 | void setResponseContent( const char *sMime, const char *sContent, int nLen ); | ||
179 | void setResponsePersistant( bool bPersistant ); | ||
180 | bool sendResponse(); | ||
181 | |||
182 | enum | ||
183 | { | ||
184 | reqOptions, | ||
185 | reqGet, | ||
186 | reqHead, | ||
187 | reqPost, | ||
188 | reqPut, | ||
189 | reqDelete, | ||
190 | reqTrace, | ||
191 | reqConnect, | ||
192 | reqExtension | ||
193 | }; | ||
194 | |||
195 | enum | ||
196 | { | ||
197 | statusContinue = 100, | ||
198 | statusSwitchProto = 101, | ||
199 | |||
200 | statusOK = 200, | ||
201 | statusCreated = 201, | ||
202 | statusAccepted = 202, | ||
203 | statusNonAuthInfo = 203, | ||
204 | statusNoContent = 204, | ||
205 | statusResetContent = 205, | ||
206 | statusPartialContent = 206, | ||
207 | |||
208 | statusMultiChoices = 300, | ||
209 | statusMovedPermanently = 301, | ||
210 | statusFound = 302, | ||
211 | statusSeeOther = 303, | ||
212 | statusNotModified = 304, | ||
213 | statusUseProxy = 305, | ||
214 | statusUnused = 306, | ||
215 | statusTempRedirect = 307, | ||
216 | |||
217 | statusBadRequest = 400, | ||
218 | statusUnauthorized = 401, | ||
219 | statusPaymentRequired = 402, | ||
220 | statusForbidden = 403, | ||
221 | statusNotFound = 404, | ||
222 | statusMethodNotAllowed = 405, | ||
223 | statusNotAcceptable = 406, | ||
224 | statusProxyAuthRequired = 407, | ||
225 | statusRequestTimeout = 408, | ||
226 | statusConflict = 409, | ||
227 | statusGone = 410, | ||
228 | statusLengthRequired = 411, | ||
229 | statusPreconditionFailed = 412, | ||
230 | statusRequestEntityTooLarge = 413, | ||
231 | statusRequestURITooLong = 414, | ||
232 | statusUnsupportedMediaType = 415, | ||
233 | statusRequestedRangeNotSatisfiable = 416, | ||
234 | statusExpectationFailed = 417, | ||
235 | |||
236 | statusInternalServerError = 500, | ||
237 | statusNotImplemented = 501, | ||
238 | statusBadGateway = 502, | ||
239 | statusServiceUnavailable = 503, | ||
240 | statusGatewayTimeout = 504, | ||
241 | statusHTTPVersionNotSupported = 505 | ||
242 | }; | ||
243 | |||
244 | private: | ||
245 | Connection *pCon; | ||
246 | unsigned char nParseState; | ||
247 | |||
248 | short nReqType; | ||
249 | std::string *pReqStr; | ||
250 | std::string sReqURI; | ||
251 | unsigned char cReqVersion; | ||
252 | HashTable hReqHeader; | ||
253 | LinkedList lStrings; | ||
254 | |||
255 | std::string sServerStr; | ||
256 | std::string sResMime; | ||
257 | std::string sResContent; | ||
258 | std::string sResStatusStr; | ||
259 | bool bResPersistant; | ||
260 | struct tm tResTime; | ||
261 | short nResStatus; | ||
262 | |||
263 | enum | ||
264 | { | ||
265 | parseInit, | ||
266 | parseHeader, | ||
267 | parseFinished | ||
268 | }; | ||
269 | }; | ||
270 | |||
271 | #endif | ||
diff --git a/src/linkedlist.cpp b/src/linkedlist.cpp new file mode 100644 index 0000000..78a615a --- /dev/null +++ b/src/linkedlist.cpp | |||
@@ -0,0 +1,227 @@ | |||
1 | /*************************************************************************** | ||
2 | linkedlist.cpp - description | ||
3 | ------------------- | ||
4 | begin : Sun Oct 19 2003 | ||
5 | copyright : (C) 2003 by Mike Buland | ||
6 | email : eichlan@yf-soft.com | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include "linkedlist.h" | ||
19 | |||
20 | LinkedList::LinkedList( ) | ||
21 | { | ||
22 | pBase = NULL; | ||
23 | pTop = NULL; | ||
24 | pLast = NULL; | ||
25 | nSize = 0; | ||
26 | nLast = -1; | ||
27 | } | ||
28 | |||
29 | LinkedList::~LinkedList( ) | ||
30 | { | ||
31 | /* | ||
32 | Link *pCur = pBase; | ||
33 | while( pCur ) | ||
34 | { | ||
35 | Link *pLast = pCur; | ||
36 | pCur = pCur->pNext; | ||
37 | delete pLast; | ||
38 | } | ||
39 | */ | ||
40 | empty(); | ||
41 | } | ||
42 | |||
43 | void *LinkedList::getAt( int index ) | ||
44 | { | ||
45 | if( index < 0 || index >= nSize ) | ||
46 | return NULL; | ||
47 | |||
48 | return getPtrTo( index )->pData; | ||
49 | } | ||
50 | |||
51 | void LinkedList::append( void *data ) | ||
52 | { | ||
53 | if( pBase == NULL ) | ||
54 | { | ||
55 | pBase = new Link( data ); | ||
56 | pTop = pBase; | ||
57 | nSize++; | ||
58 | } | ||
59 | else | ||
60 | { | ||
61 | pTop->pNext = new Link( data ); | ||
62 | pTop = pTop->pNext; | ||
63 | nSize++; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | void LinkedList::insertBefore( void *data, int pos ) | ||
68 | { | ||
69 | if( pos < 0 || pos > nSize ) | ||
70 | return; | ||
71 | |||
72 | if( pos == 0 ) | ||
73 | { | ||
74 | Link *pTmp = new Link( data, pBase ); | ||
75 | if( pBase == NULL ) | ||
76 | { | ||
77 | pTop = pTmp; | ||
78 | } | ||
79 | pBase = pTmp; | ||
80 | if( nLast >= 0 ) nLast++; | ||
81 | nSize++; | ||
82 | } | ||
83 | else | ||
84 | { | ||
85 | Link *pCur; | ||
86 | if( (pCur = getPtrTo( pos-1 )) == NULL ) | ||
87 | { | ||
88 | return; | ||
89 | } | ||
90 | Link *pNew = new Link( data, pCur->pNext ); | ||
91 | pCur->pNext = pNew; | ||
92 | if( pNew->pNext == NULL ) | ||
93 | { | ||
94 | pTop = pNew; | ||
95 | } | ||
96 | if( nLast >= pos ) nLast++; | ||
97 | nSize++; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | int LinkedList::getSize( ) | ||
102 | { | ||
103 | return nSize; | ||
104 | } | ||
105 | |||
106 | bool LinkedList::isEmpty( ) | ||
107 | { | ||
108 | if( nSize == 0 ) | ||
109 | return true; | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | void LinkedList::deleteAt( int index ) | ||
114 | { | ||
115 | if( index >= nSize || | ||
116 | pBase == NULL ) | ||
117 | return; | ||
118 | |||
119 | if( index == 0 ) | ||
120 | { | ||
121 | Link *pTmp = pBase->pNext; | ||
122 | delete pBase; | ||
123 | pBase = pTmp; | ||
124 | if( nLast >= 0 ) nLast--; | ||
125 | nSize--; | ||
126 | if( pBase == NULL ) | ||
127 | { | ||
128 | pTop = NULL; | ||
129 | } | ||
130 | else if( pBase->pNext == NULL ) | ||
131 | { | ||
132 | pTop = pBase; | ||
133 | } | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | Link *pCur = getPtrTo( index-1 ); | ||
138 | if( pCur->pNext == pTop ) | ||
139 | { | ||
140 | pTop = pCur; | ||
141 | } | ||
142 | Link *pTmp; | ||
143 | if( pCur->pNext == NULL ) | ||
144 | { | ||
145 | pTmp = NULL; | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | pTmp = pCur->pNext->pNext; | ||
150 | } | ||
151 | delete pCur->pNext; | ||
152 | pCur->pNext = pTmp; | ||
153 | if( nLast == index ) nLast = -1; | ||
154 | else if( index < nLast ) nLast--; | ||
155 | nSize--; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | void LinkedList::empty() | ||
160 | { | ||
161 | while( nSize > 0 ) | ||
162 | { | ||
163 | deleteAt( 0 ); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | void LinkedList::setSize( int newSize ) | ||
168 | { | ||
169 | if( newSize < nSize ) | ||
170 | { | ||
171 | // Delete items off of the end of the list. | ||
172 | while( nSize > newSize ) | ||
173 | { | ||
174 | deleteAt( nSize-1 ); | ||
175 | } | ||
176 | } | ||
177 | else | ||
178 | { | ||
179 | // Add null items to the end of the list. | ||
180 | while( nSize < newSize ) | ||
181 | { | ||
182 | append( NULL ); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | void LinkedList::setAt( int index, void *data ) | ||
188 | { | ||
189 | if( index >= nSize || index < 0 ) | ||
190 | return; | ||
191 | |||
192 | getPtrTo( index )->pData = data; | ||
193 | } | ||
194 | |||
195 | LinkedList::Link *LinkedList::getPtrTo( int index ) | ||
196 | { | ||
197 | if( index < 0 || index >= nSize ) | ||
198 | return NULL; | ||
199 | if( index == nLast ) | ||
200 | { | ||
201 | return pLast; | ||
202 | } | ||
203 | if( index == 0 ) | ||
204 | { | ||
205 | pLast = pBase; | ||
206 | nLast = 0; | ||
207 | return pBase; | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | Link *pCur = pBase; | ||
212 | int nCur = 0; | ||
213 | if( nLast < index && nLast >= 0 ) | ||
214 | { | ||
215 | pCur = pLast; | ||
216 | nCur = nLast; | ||
217 | } | ||
218 | while( nCur != index ) | ||
219 | { | ||
220 | pCur = pCur->pNext; | ||
221 | nCur++; | ||
222 | } | ||
223 | nLast = index; | ||
224 | pLast = pCur; | ||
225 | return pCur; | ||
226 | } | ||
227 | } | ||
diff --git a/src/linkedlist.h b/src/linkedlist.h new file mode 100644 index 0000000..c45cc9b --- /dev/null +++ b/src/linkedlist.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /**@file | ||
2 | * Describes the LinkedList implementation of the List ADT. | ||
3 | *@author Mike Buland | ||
4 | */ | ||
5 | |||
6 | #ifndef LINKEDLIST_H | ||
7 | #define LINKEDLIST_H | ||
8 | |||
9 | #include <stdio.h> | ||
10 | #include "list.h" | ||
11 | |||
12 | /** A linked-item implementation of the List ADT. Since the data is linked | ||
13 | * sequentially this is a great choice for lists that will grow and shrink | ||
14 | * a lot, but don't require as much random access. This implementation | ||
15 | * includes optomizations that make iterating through data, and appending | ||
16 | * items to the list take O(1) time. | ||
17 | *@author Mike Buland | ||
18 | */ | ||
19 | class LinkedList : public List | ||
20 | { | ||
21 | public: | ||
22 | /** | ||
23 | * Construct a blank LinkedList. | ||
24 | */ | ||
25 | LinkedList(); | ||
26 | |||
27 | /** | ||
28 | * Delete all list data, but do not delete any of the contained elements. | ||
29 | */ | ||
30 | ~LinkedList(); | ||
31 | |||
32 | void *getAt( int nIndex ); | ||
33 | void append( void *pData ); | ||
34 | void insertBefore( void *pData, int nPos = 0 ); | ||
35 | int getSize( ); | ||
36 | bool isEmpty( ); | ||
37 | void deleteAt( int nIndex ); | ||
38 | void empty(); | ||
39 | void setSize( int nNewSize ); | ||
40 | void setAt( int nIndex, void *pData ); | ||
41 | |||
42 | private: | ||
43 | /** | ||
44 | * A link in the linked list. | ||
45 | */ | ||
46 | class Link | ||
47 | { | ||
48 | public: | ||
49 | /** | ||
50 | * Construct an empty link. | ||
51 | */ | ||
52 | Link() | ||
53 | { | ||
54 | pData = NULL; | ||
55 | pNext = NULL; | ||
56 | } | ||
57 | /** | ||
58 | * Construct a link filled in with useful data. | ||
59 | *@param newData The data this link should hold. | ||
60 | *@param newNext The next link that this link should point to. | ||
61 | */ | ||
62 | Link( void *newData = NULL, Link * newNext = NULL ) | ||
63 | { | ||
64 | pData = newData; | ||
65 | pNext = newNext; | ||
66 | } | ||
67 | void *pData; /**< A pointer to the contained data. */ | ||
68 | Link *pNext; /**< A pointer to the next link in the chain */ | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * Finds a pointer to the link at index index. This is the core function | ||
73 | * called for all seek operations, and has been optimized as heavily as | ||
74 | * possible. | ||
75 | *@param index The zero-based index of the desired element. | ||
76 | *@returns A pointer to the requested Link, or NULL if it isn't found. | ||
77 | */ | ||
78 | Link *getPtrTo( int index ); | ||
79 | Link *pBase; /**< The first link in the list. */ | ||
80 | Link *pTop; /**< The Last link in the list. */ | ||
81 | Link *pLast; /**< The previously requested link. */ | ||
82 | int nSize; /**< The number of contained links. */ | ||
83 | int nLast; /**< The index of the previously requested link. */ | ||
84 | }; | ||
85 | |||
86 | #endif | ||
87 | |||
diff --git a/src/linkmessage.cpp b/src/linkmessage.cpp new file mode 100644 index 0000000..ce838f5 --- /dev/null +++ b/src/linkmessage.cpp | |||
@@ -0,0 +1,53 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2003 by Mike Buland * | ||
3 | * eichlan@yf-soft.com * | ||
4 | * * | ||
5 | * This program is free software; you can redistribute it and/or modify * | ||
6 | * it under the terms of the GNU General Public License as published by * | ||
7 | * the Free Software Foundation; either version 2 of the License, or * | ||
8 | * (at your option) any later version. * | ||
9 | ***************************************************************************/ | ||
10 | #include "linkmessage.h" | ||
11 | #include <string.h> | ||
12 | |||
13 | LinkMessage::LinkMessage( int nNewMsg ) | ||
14 | { | ||
15 | nMsg = nNewMsg; | ||
16 | } | ||
17 | |||
18 | LinkMessage::~LinkMessage() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | /* | ||
23 | void LinkMessage::setBroadcast( bool bOn ) | ||
24 | { | ||
25 | bBroadcast = bOn; | ||
26 | } | ||
27 | |||
28 | bool LinkMessage::isBroadcast() | ||
29 | { | ||
30 | return bBroadcast; | ||
31 | } | ||
32 | |||
33 | |||
34 | void LinkMessage::setFromID( int id ) | ||
35 | { | ||
36 | nFromLinkID = id; | ||
37 | } | ||
38 | |||
39 | int LinkMessage::getFromID() | ||
40 | { | ||
41 | return nFromLinkID; | ||
42 | } | ||
43 | |||
44 | void LinkMessage::setToID( int id ) | ||
45 | { | ||
46 | nTargetLinkID = id; | ||
47 | } | ||
48 | |||
49 | int LinkMessage::getToID() | ||
50 | { | ||
51 | return nTargetLinkID; | ||
52 | } | ||
53 | */ | ||
diff --git a/src/linkmessage.h b/src/linkmessage.h new file mode 100644 index 0000000..6cdfb2f --- /dev/null +++ b/src/linkmessage.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /**\file linkmessage.h | ||
2 | */ | ||
3 | |||
4 | #ifndef LINKMESSAGE_H | ||
5 | #define LINKMESSAGE_H | ||
6 | |||
7 | /** | ||
8 | * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally | ||
9 | * one would make a subclass of this in order to transmit more useful | ||
10 | * information, but sometimes it isn't necesarry. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class LinkMessage | ||
14 | { | ||
15 | public: | ||
16 | /** | ||
17 | * Construct a blank LinkMessage. | ||
18 | */ | ||
19 | LinkMessage() {}; | ||
20 | |||
21 | /** | ||
22 | * Deconstruct a LinkMessage. | ||
23 | */ | ||
24 | virtual ~LinkMessage(); | ||
25 | |||
26 | /** | ||
27 | * Create a LinkMessage object with a specific message assosiated with it | ||
28 | * to start with. | ||
29 | *@param nNewMsg The message to use in the Message object. | ||
30 | */ | ||
31 | LinkMessage( int nNewMsg ); | ||
32 | |||
33 | /** | ||
34 | * The message contained in the Message object. | ||
35 | */ | ||
36 | int nMsg; | ||
37 | }; | ||
38 | |||
39 | #endif | ||
diff --git a/src/list.cpp b/src/list.cpp new file mode 100644 index 0000000..c8b88c1 --- /dev/null +++ b/src/list.cpp | |||
@@ -0,0 +1,27 @@ | |||
1 | /*************************************************************************** | ||
2 | list.cpp - description | ||
3 | ------------------- | ||
4 | begin : Sun Oct 19 2003 | ||
5 | copyright : (C) 2003 by Mike Buland | ||
6 | email : eichlan@yf-soft.com | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include "list.h" | ||
19 | |||
20 | List::List( ) | ||
21 | { | ||
22 | } | ||
23 | |||
24 | List::~List( ) | ||
25 | { | ||
26 | } | ||
27 | |||
diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..c71b328 --- /dev/null +++ b/src/list.h | |||
@@ -0,0 +1,101 @@ | |||
1 | #ifndef LIST_H | ||
2 | #define LIST_H | ||
3 | |||
4 | |||
5 | /** The basic List class ADT. This, on it's own, does absolutely nothing, but | ||
6 | * does define all standard interface functions to access a list. | ||
7 | *@author Mike Buland | ||
8 | */ | ||
9 | class List | ||
10 | { | ||
11 | public: | ||
12 | /** | ||
13 | * Construct a list. | ||
14 | */ | ||
15 | List(); | ||
16 | |||
17 | /** | ||
18 | * Desconstruct a list. | ||
19 | */ | ||
20 | virtual ~List(); | ||
21 | |||
22 | /** Gets the value at a specified index. | ||
23 | *@param nIndex The index of the item to return. | ||
24 | *@returns The specified item, or NULL if the index was beyond the range | ||
25 | * of the list. | ||
26 | *@author Mike Buland | ||
27 | */ | ||
28 | virtual void *getAt( int nIndex ) = 0; | ||
29 | |||
30 | /** Append the given data to the end of the list. This increases the | ||
31 | * size of the list by one. | ||
32 | *@param pData The data to append to the list. | ||
33 | *@author Mike Buland | ||
34 | */ | ||
35 | virtual void append( void *pData ) = 0; | ||
36 | |||
37 | /** Inserts an item at the specified position in the list. The | ||
38 | * new item takes the index that you specify, and all other items | ||
39 | * are moved up one position. The size of the list is increased by | ||
40 | * one. | ||
41 | *@param pData The value to insert into the list. | ||
42 | *@param nPos Where to insert the data into the list. | ||
43 | *@author Mike Buland | ||
44 | */ | ||
45 | virtual void insertBefore( void *pData, int nPos = 0 ) = 0; | ||
46 | |||
47 | /** Determines the size of the list, in elements. | ||
48 | *@returns The size of the list. | ||
49 | *@author Mike Buland | ||
50 | */ | ||
51 | virtual int getSize( ) = 0; | ||
52 | |||
53 | /** Determines if the list is empty or not. | ||
54 | *@returns True if the list is empty, or false if the list has | ||
55 | * data in it (if the size is greater than zero). | ||
56 | *@author Mike Buland | ||
57 | */ | ||
58 | virtual bool isEmpty( ) = 0; | ||
59 | |||
60 | /** Deletes an item at the specified index and moves all other | ||
61 | * values down one index. The size of the list is decreased by one. | ||
62 | *@param nIndex The index of the item to delete. | ||
63 | *@author Mike Buland | ||
64 | */ | ||
65 | virtual void deleteAt( int nIndex ) = 0; | ||
66 | |||
67 | /** Completely empties the list, and sets the effective size to | ||
68 | * zero. | ||
69 | *@author Mike Buland | ||
70 | */ | ||
71 | virtual void empty() = 0; | ||
72 | |||
73 | /** Sets the size of the list. This can be larger or smaller | ||
74 | * than what it was previously. If larger, new blank items will | ||
75 | * be added to the end of the list. If smaller than the old list | ||
76 | * items will be deleted from the end. | ||
77 | *@param nNewSize The new size of the list. | ||
78 | *@author Mike Buland | ||
79 | */ | ||
80 | virtual void setSize( int nNewSize ) = 0; | ||
81 | |||
82 | /** Sets a member at a specified location to a new value. | ||
83 | * If the member being set is outside of the range of the | ||
84 | * current list it should be expanded. | ||
85 | *@param nIndex The zero-based index of the item to change. | ||
86 | *@param pData The new value for that index. | ||
87 | *@author Mike Buland | ||
88 | */ | ||
89 | virtual void setAt( int nIndex, void *pData ) = 0; | ||
90 | |||
91 | /** Makes the List work like an array. Just say listObj[2] to get | ||
92 | * the third element. | ||
93 | *@param nIndex The index to access in the list. | ||
94 | *@returns A pointer to the data at element index. | ||
95 | *@author Mike Buland | ||
96 | */ | ||
97 | void *operator[]( int nIndex ) { return getAt( nIndex ); }; | ||
98 | }; | ||
99 | |||
100 | #endif | ||
101 | |||
diff --git a/src/md5.cpp b/src/md5.cpp new file mode 100644 index 0000000..ed7e4ac --- /dev/null +++ b/src/md5.cpp | |||
@@ -0,0 +1,190 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include "md5.h" | ||
5 | |||
6 | // This is a fun macro that tells us where the length char goes after the data | ||
7 | // section in the padded data segment. It's short for OBfuscation LOCaction. | ||
8 | #define OBLOC(len) ((((len + 64) >> 9) << 4) + 14) | ||
9 | // This performs a wrapping bitwise shift, kinda' fun! | ||
10 | |||
11 | #define bit_roll( num, cnt ) \ | ||
12 | (((num) << (cnt)) | (((num) >> (32 - (cnt))) & ~(-1<<(cnt)))) | ||
13 | |||
14 | //#define md5_cmn( q, a, b, x, s, t ) (bit_roll((a + q + x + t), s) + b) | ||
15 | |||
16 | // The following are handy wrappers for the cmn function | ||
17 | #define md5_ff( a, b, c, d, x, s, t ) \ | ||
18 | (md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)) | ||
19 | |||
20 | #define md5_gg( a, b, c, d, x, s, t ) \ | ||
21 | (md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)) | ||
22 | |||
23 | #define md5_hh( a, b, c, d, x, s, t ) \ | ||
24 | (md5_cmn(b ^ c ^ d, a, b, x, s, t)) | ||
25 | |||
26 | #define md5_ii( a, b, c, d, x, s, t ) \ | ||
27 | (md5_cmn(c ^ (b | (~d)), a, b, x, s, t)) | ||
28 | |||
29 | inline long md5_cmn( long q, long a, long b, long x, long s, long t ) | ||
30 | { | ||
31 | return bit_roll((a + q + x + t), s) + b; | ||
32 | } | ||
33 | |||
34 | md5::md5() | ||
35 | { | ||
36 | } | ||
37 | |||
38 | md5::~md5() | ||
39 | { | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * Calculate the MD5 of an array of little-endian words, and a bit length | ||
44 | */ | ||
45 | void md5::core_md5( long *x, long len, md5sum *output ) | ||
46 | { | ||
47 | long a = 1732584193, olda; | ||
48 | long b = -271733879, oldb; | ||
49 | long c = -1732584194, oldc; | ||
50 | long d = 271733878, oldd; | ||
51 | |||
52 | for( long i = 0; i < len; i += 16 ) | ||
53 | { | ||
54 | olda = a; | ||
55 | oldb = b; | ||
56 | oldc = c; | ||
57 | oldd = d; | ||
58 | |||
59 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | ||
60 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | ||
61 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); | ||
62 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); | ||
63 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); | ||
64 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); | ||
65 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); | ||
66 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); | ||
67 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); | ||
68 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); | ||
69 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063); | ||
70 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); | ||
71 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); | ||
72 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); | ||
73 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | ||
74 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | ||
75 | |||
76 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | ||
77 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | ||
78 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); | ||
79 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); | ||
80 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); | ||
81 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); | ||
82 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); | ||
83 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); | ||
84 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); | ||
85 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); | ||
86 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); | ||
87 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); | ||
88 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); | ||
89 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); | ||
90 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | ||
91 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | ||
92 | |||
93 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | ||
94 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | ||
95 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); | ||
96 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); | ||
97 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); | ||
98 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); | ||
99 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); | ||
100 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); | ||
101 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); | ||
102 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); | ||
103 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); | ||
104 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); | ||
105 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); | ||
106 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); | ||
107 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | ||
108 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | ||
109 | |||
110 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | ||
111 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | ||
112 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); | ||
113 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); | ||
114 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); | ||
115 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); | ||
116 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); | ||
117 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); | ||
118 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); | ||
119 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); | ||
120 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); | ||
121 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); | ||
122 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); | ||
123 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); | ||
124 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | ||
125 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | ||
126 | |||
127 | a = a + olda; | ||
128 | b = b + oldb; | ||
129 | c = c + oldc; | ||
130 | d = d + oldd; | ||
131 | } | ||
132 | |||
133 | output->data[0] = a; | ||
134 | output->data[1] = b; | ||
135 | output->data[2] = c; | ||
136 | output->data[3] = d; | ||
137 | delete[] x; | ||
138 | } | ||
139 | |||
140 | long *md5::c2l( const char *str, long len, long *nNewLen ) | ||
141 | { | ||
142 | long len8 = len*8; | ||
143 | long mlen = OBLOC( len8 ); | ||
144 | long flen = (((mlen/16)+((mlen%16)?(1):(0))))*16; | ||
145 | long *aBin = new long[flen]; | ||
146 | memset( aBin, 0, flen ); | ||
147 | |||
148 | for( long i = 0; i < len8; i+=8 ) | ||
149 | { | ||
150 | aBin[i>>5] |= ((long)str[i/8]) << (i%32); | ||
151 | } | ||
152 | |||
153 | aBin[len8 >> 5] |= 0x80 << ((len8) % 32); | ||
154 | aBin[OBLOC( len8 )] = len8; | ||
155 | |||
156 | (*nNewLen) = flen; | ||
157 | |||
158 | return aBin; | ||
159 | } | ||
160 | |||
161 | void md5::l2hexstr( long *binarray, char *str ) | ||
162 | { | ||
163 | static const char hex_tab[] = {"0123456789abcdef"}; | ||
164 | //static char str[33]; | ||
165 | |||
166 | int k = 0; | ||
167 | for( int i = 0; i < 16; i++) | ||
168 | { | ||
169 | str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8+4)) & 0xF]; | ||
170 | str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8 )) & 0xF]; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | void md5::sumString( md5sum *pSum, const char *sStr ) | ||
175 | { | ||
176 | sumData( pSum, sStr, strlen( sStr ) ); | ||
177 | } | ||
178 | |||
179 | void md5::sumData( md5sum *pSum, const char *aData, long nLen ) | ||
180 | { | ||
181 | long nNewLen; | ||
182 | long *aOb = c2l( aData, nLen, &nNewLen ); | ||
183 | core_md5( aOb, nNewLen, pSum ); | ||
184 | } | ||
185 | |||
186 | void md5::sumToHex( md5sum *pSum, char *sHex ) | ||
187 | { | ||
188 | l2hexstr( pSum->data, sHex ); | ||
189 | } | ||
190 | |||
diff --git a/src/md5.h b/src/md5.h new file mode 100644 index 0000000..810345e --- /dev/null +++ b/src/md5.h | |||
@@ -0,0 +1,81 @@ | |||
1 | #ifndef MD5_H | ||
2 | #define MD5_H | ||
3 | |||
4 | /** | ||
5 | * Used to store an MD5 sum in a handy container. | ||
6 | */ | ||
7 | typedef struct | ||
8 | { | ||
9 | /** The actual data-storage for an MD5 sum. */ | ||
10 | long data[4]; | ||
11 | } md5sum; | ||
12 | |||
13 | /** | ||
14 | * Class for easily calculating MD5 sums of just about any data. | ||
15 | *@author Mike Buland | ||
16 | */ | ||
17 | class md5 | ||
18 | { | ||
19 | public: | ||
20 | /** Build an MD5 sum builder. */ | ||
21 | md5(); | ||
22 | |||
23 | /** Deconstruct */ | ||
24 | ~md5(); | ||
25 | |||
26 | /** | ||
27 | * Create a sum of a standard c string, null terminated. This is probably | ||
28 | * the easiest function to use. | ||
29 | *@param pSum The MD5 sum structure to fill up. | ||
30 | *@param sStr The null-terminated string to turn into an MD5 sum. | ||
31 | */ | ||
32 | void sumString( md5sum *pSum, const char *sStr ); | ||
33 | |||
34 | /** | ||
35 | * Create a sum of an array of arbitrary data. This is the most handy for | ||
36 | * dealing with files and so on. | ||
37 | *@param pSum The MD5 sum structure to fill up. | ||
38 | *@param aData A pointer to the base of the data to sum. | ||
39 | *@param nLen The number of bytes to use in the sum. | ||
40 | */ | ||
41 | void sumData( md5sum *pSum, const char *aData, long nLen ); | ||
42 | |||
43 | /** | ||
44 | * Convert an md5sum to standard hex representation. Make sure that sHex | ||
45 | * contains at least 17 characters of space. | ||
46 | *@param pSum The sum structure to convert to hex. | ||
47 | *@param sHex The string to store the hex value in. | ||
48 | */ | ||
49 | void sumToHex( md5sum *pSum, char *sHex ); | ||
50 | |||
51 | private: | ||
52 | /** | ||
53 | * Do the bulk of the work of the md5 algorithm. | ||
54 | *@param x I'm not sure. I'll need to look it up. | ||
55 | *@param len The length of the data. | ||
56 | *@param output The sum structure to put the output in. | ||
57 | */ | ||
58 | void core_md5( long *x, long len, md5sum *output ); | ||
59 | |||
60 | /** | ||
61 | * Convert an array of charaters to an array of longs in a very crafty way. | ||
62 | * This also applies standard MD5 obfuscation to the resulting array, and | ||
63 | * makes it fit within MD5 size constraints. | ||
64 | *@param str The data to convert. | ||
65 | *@param len The length of the data. | ||
66 | *@param nNewLen A pointer to a variable that will hold the new length of | ||
67 | * the resulting array of longs. | ||
68 | *@returns The newly obfuscated and resized long array. | ||
69 | */ | ||
70 | long *c2l( const char *str, long len, long *nNewLen ); | ||
71 | |||
72 | /** | ||
73 | * Backend helper to convert an array of longs into a hex string. | ||
74 | *@param binarray The binary data to convert. | ||
75 | *@param str The string to store the hex string in. | ||
76 | */ | ||
77 | void l2hexstr( long *binarray, char *str ); | ||
78 | |||
79 | }; | ||
80 | |||
81 | #endif | ||
diff --git a/src/multilog.cpp b/src/multilog.cpp new file mode 100644 index 0000000..64ff967 --- /dev/null +++ b/src/multilog.cpp | |||
@@ -0,0 +1,143 @@ | |||
1 | /*************************************************************************** | ||
2 | multilog.cpp - description | ||
3 | ------------------- | ||
4 | begin : Sat Sep 6 2003 | ||
5 | copyright : (C) 2003 by Mike Buland | ||
6 | email : eichlan@yf-soft.com | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include "multilog.h" | ||
19 | #include <stdio.h> | ||
20 | #include <time.h> | ||
21 | #include <string.h> | ||
22 | #include <stdlib.h> | ||
23 | |||
24 | #include "multilogchannel.h" | ||
25 | |||
26 | // This section is what we need to make this a singleton | ||
27 | // this makes this class easy to use from anywhere, without | ||
28 | // worrying about re-creating every output form and all of that crazy jazz | ||
29 | MultiLog *MultiLog::singleLog = NULL; | ||
30 | |||
31 | MultiLog *MultiLog::getLog() | ||
32 | { | ||
33 | if( singleLog == NULL ) | ||
34 | { | ||
35 | singleLog = new MultiLog; | ||
36 | atexit( cleanup ); | ||
37 | } | ||
38 | return singleLog; | ||
39 | } | ||
40 | |||
41 | void MultiLog::cleanup() | ||
42 | { | ||
43 | if( singleLog != NULL ) | ||
44 | { | ||
45 | delete singleLog; | ||
46 | singleLog = NULL; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | MultiLog::MultiLog() | ||
51 | { | ||
52 | lChannel = new LinkedList(); | ||
53 | rEntry = new RingList( 150 ); | ||
54 | nEntriesLost = 0; | ||
55 | } | ||
56 | |||
57 | MultiLog::~MultiLog() | ||
58 | { | ||
59 | int nMax = lChannel->getSize(); | ||
60 | for( int j = 0; j < nMax; j++ ) | ||
61 | { | ||
62 | ((MultiLogChannel *)lChannel->getAt(j))->closeLog(); | ||
63 | delete ((MultiLogChannel *)lChannel->getAt(j)); | ||
64 | } | ||
65 | delete lChannel; | ||
66 | |||
67 | for( int j = 0; j < rEntry->getSize(); j++ ) | ||
68 | { | ||
69 | delete (LogEntry *)rEntry->getAt( j ); | ||
70 | } | ||
71 | delete rEntry; | ||
72 | } | ||
73 | /* | ||
74 | void MultiLog::Log( int nLevel, const char *lpFormat, ...) | ||
75 | { | ||
76 | switch( nLevel ) | ||
77 | { | ||
78 | default: | ||
79 | break; | ||
80 | } | ||
81 | va_list ap; | ||
82 | va_start(ap, lpFormat); | ||
83 | |||
84 | vprintf( lpFormat, ap ); | ||
85 | |||
86 | va_end(ap); | ||
87 | }*/ | ||
88 | |||
89 | void MultiLog::DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...) | ||
90 | { | ||
91 | LogEntry *e = new LogEntry(); | ||
92 | |||
93 | va_list ap; | ||
94 | va_start(ap, lpFormat); | ||
95 | char *text; | ||
96 | vasprintf( &text, lpFormat, ap ); | ||
97 | va_end(ap); | ||
98 | |||
99 | time( &e->xTime ); | ||
100 | e->nLevel = nLevel; | ||
101 | e->nLine = nLine; | ||
102 | e->lpFile = new char[strlen(lpFile)+1]; | ||
103 | strcpy( e->lpFile, lpFile ); | ||
104 | e->lpText = new char[strlen(text)+1]; | ||
105 | strcpy( e->lpText, text ); | ||
106 | free( text ); | ||
107 | |||
108 | append( e ); | ||
109 | } | ||
110 | |||
111 | void MultiLog::append( LogEntry *pEntry ) | ||
112 | { | ||
113 | rEntry->append( pEntry ); | ||
114 | if( rEntry->getPushBuf() ) | ||
115 | { | ||
116 | delete (LogEntry *)rEntry->getPushBuf(); | ||
117 | nEntriesLost++; | ||
118 | } | ||
119 | |||
120 | for( int j = 0; j < lChannel->getSize(); j++ ) | ||
121 | { | ||
122 | ((MultiLogChannel *)lChannel->getAt( j ))->append( pEntry ); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | void MultiLog::addChannel( MultiLogChannel *pChannel ) | ||
127 | { | ||
128 | lChannel->append( pChannel ); | ||
129 | |||
130 | pChannel->openLog(); | ||
131 | |||
132 | for( int j = 0; j < rEntry->getSize(); j++ ) | ||
133 | { | ||
134 | pChannel->append( (LogEntry *)rEntry->getAt( j ) ); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | MultiLog::LogEntry::~LogEntry() | ||
139 | { | ||
140 | delete[] lpFile; | ||
141 | delete[] lpText; | ||
142 | } | ||
143 | |||
diff --git a/src/multilog.h b/src/multilog.h new file mode 100644 index 0000000..30ad8d7 --- /dev/null +++ b/src/multilog.h | |||
@@ -0,0 +1,145 @@ | |||
1 | #ifndef MULTILOG_H | ||
2 | #define MULTILOG_H | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdarg.h> | ||
6 | #include <time.h> | ||
7 | |||
8 | #include "ringlist.h" | ||
9 | #include "linkedlist.h" | ||
10 | |||
11 | /** | ||
12 | * Calls the DetailLog function but includes pre-processor macros to fill in | ||
13 | * most of the fields for you. This makes your life a lot easier, and makes the | ||
14 | * log useful for system debugging as well as just letting people know what's | ||
15 | * going on. | ||
16 | *@param LEVEL The log level, comes from an enum in the MultiLog class. | ||
17 | *@param FORMAT The text to store in the log, using printf style formatting. | ||
18 | *@param ... Parameters to help format the text in the FROMAT param. | ||
19 | */ | ||
20 | #define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) | ||
21 | |||
22 | /** MultiLog keeps track of logfile info in a myriad of varieties, and is | ||
23 | * easily configurable between them all. It allows output to the standard | ||
24 | * output, error output, files, networks, and streams, which includes memory | ||
25 | * buffers. | ||
26 | * MultiLog uses the singleton pattern to keep only a single instance of | ||
27 | * the log. Instead of instantiating a new copy, call the getLog method. | ||
28 | *@author Mike Buland | ||
29 | */ | ||
30 | class MultiLog | ||
31 | { | ||
32 | public: | ||
33 | /** | ||
34 | * Keeps track of a single log entry, in a standard format, that can be | ||
35 | * processed by any MultiLogChannel derrived class. | ||
36 | *@author Mike Buland | ||
37 | */ | ||
38 | typedef struct LogEntry | ||
39 | { | ||
40 | /** Safely delete a log entry. */ | ||
41 | ~LogEntry(); | ||
42 | time_t xTime; /**< The time the log entry was made. */ | ||
43 | int nLevel; /**< The log-level of the entry. */ | ||
44 | char *lpFile; /**< The name of the file this entry came from. */ | ||
45 | int nLine; /**< The line number that this log came from. */ | ||
46 | char *lpText; /**< The text content of this log entry. */ | ||
47 | } LogEntry; | ||
48 | |||
49 | private: | ||
50 | /** | ||
51 | * Private constructor, this ensures that this is a singleton. | ||
52 | */ | ||
53 | MultiLog(); | ||
54 | |||
55 | /** | ||
56 | * The only instance of MultiLog ever. | ||
57 | */ | ||
58 | static MultiLog *singleLog; | ||
59 | |||
60 | /** | ||
61 | * Append a new logentry to the log list, possibly pushing an old entry off. | ||
62 | *@param pEntry The new entry to append. | ||
63 | */ | ||
64 | void append( LogEntry *pEntry ); | ||
65 | |||
66 | /** | ||
67 | * The actual log entry storage mechanism. | ||
68 | */ | ||
69 | RingList *rEntry; | ||
70 | |||
71 | /** | ||
72 | * The number of entries that have rolled off the end of the RingList. | ||
73 | */ | ||
74 | unsigned long nEntriesLost; | ||
75 | |||
76 | /** | ||
77 | * A list of all channels that are registered with the MultiLog. | ||
78 | */ | ||
79 | LinkedList *lChannel; | ||
80 | |||
81 | public: | ||
82 | /** | ||
83 | * Destroy the multilog. | ||
84 | *@todo Why is this public? Does it need to be? | ||
85 | */ | ||
86 | ~MultiLog(); | ||
87 | |||
88 | /** Sends info to the logfile. | ||
89 | *@param nLevel The type of data being logged (error, info, etc.) | ||
90 | *@param lpFormat The data to send to the log. | ||
91 | *@author Mike Buland | ||
92 | */ | ||
93 | //void Log( int nLevel, const char *lpFormat, ...); | ||
94 | |||
95 | /** Sends info to the logfile with extra information, including the files | ||
96 | * that it was called from and the line in the code. Besides that, it's | ||
97 | * exactly the same as Log. Please use the LineLog macro to make DetailLog | ||
98 | * really easy to use. It operates exacly like Log, but inserts the | ||
99 | * builtin macros as the lpFile and nLine parameters. | ||
100 | *@param nLevel The type of data being logged (error, info, etc.) | ||
101 | *@param lpFile The name of the file that called the log function. | ||
102 | *@param nLine The line in the file that this log function was called from. | ||
103 | *@param lpFunction The name of the function that called the log function. | ||
104 | *@param lpFormat The data to send to the log. | ||
105 | *@author Mike Buland | ||
106 | */ | ||
107 | void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...); | ||
108 | |||
109 | /** Gets a pointer to the only instantion of the MultiLog that can exist. | ||
110 | * If there is no instantion in existance, it creates one, so it's | ||
111 | * foolproof. | ||
112 | *@returns A pointer to the only MultiLog instantion. | ||
113 | *@author Mike Buland | ||
114 | */ | ||
115 | static MultiLog *getLog(); | ||
116 | |||
117 | /** Performs standard cleanup and deletes the only instantiation of MultiLog | ||
118 | * that can exist. This is just the same as delete and will nicely close | ||
119 | * all open logs. always call this when you are done with your MultiLog. | ||
120 | */ | ||
121 | static void cleanup(); | ||
122 | |||
123 | /** | ||
124 | * Adds a logging channel to the MultiLog channel chain. Every added | ||
125 | * channel will automatically receive a complete log of everything that | ||
126 | * happened before the channel was added as well as all future messages. | ||
127 | *@param pChannel A pointer to the pre-contructed channel object to add. | ||
128 | */ | ||
129 | void addChannel( class MultiLogChannel *pChannel ); | ||
130 | |||
131 | /** The various pre-defined levels available to use when logging. | ||
132 | * The person logging can make up their own, just make sure to remember | ||
133 | * which value is which (all levels are integers). | ||
134 | *@author Mike Buland | ||
135 | */ | ||
136 | enum Levels | ||
137 | { | ||
138 | LError, | ||
139 | LWarning, | ||
140 | LInfo, | ||
141 | LStatus | ||
142 | }; | ||
143 | }; | ||
144 | |||
145 | #endif | ||
diff --git a/src/multilogchannel.cpp b/src/multilogchannel.cpp new file mode 100644 index 0000000..ee4c9bf --- /dev/null +++ b/src/multilogchannel.cpp | |||
@@ -0,0 +1,13 @@ | |||
1 | // | ||
2 | // C++ Implementation: multilogchannel | ||
3 | // | ||
4 | // Description: | ||
5 | // | ||
6 | // | ||
7 | // Author: Mike Buland <eichlan@yf-soft.com>, (C) 2005 | ||
8 | // | ||
9 | // Copyright: See COPYING file that comes with this distribution | ||
10 | // | ||
11 | // | ||
12 | #include "multilogchannel.h" | ||
13 | |||
diff --git a/src/multilogchannel.h b/src/multilogchannel.h new file mode 100644 index 0000000..d891a65 --- /dev/null +++ b/src/multilogchannel.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef MULTILOGCHANNEL_H | ||
2 | #define MULTILOGCHANNEL_H | ||
3 | |||
4 | #include "multilog.h" | ||
5 | |||
6 | /** | ||
7 | * The baseclass for any MultiLog output channel. Any class that implements | ||
8 | * all of these functions can be put in the log chain and will be sent | ||
9 | * messages from active MultiLoggers. | ||
10 | *@author Mike Buland | ||
11 | */ | ||
12 | class MultiLogChannel | ||
13 | { | ||
14 | public: | ||
15 | /** | ||
16 | * Deconstruct a MultiLogChannel. | ||
17 | */ | ||
18 | virtual ~MultiLogChannel() {}; | ||
19 | |||
20 | /** | ||
21 | * Should perform any operations that need to take place in order to start | ||
22 | * the output of data into this channel. This will be called once by the | ||
23 | * MultiLog when the MultiLogChannel is registered. | ||
24 | *@returns True means that everything can go as planned. False means that | ||
25 | * the MultiLog should remove this channel from the list and delete it. | ||
26 | */ | ||
27 | virtual bool openLog() = 0; | ||
28 | |||
29 | /** | ||
30 | * Should append a log entry to the long, by whatever means are necesarry. | ||
31 | *@param pEntry The LogEntry to append. | ||
32 | *@returns True means that everything can go as planned. False means that | ||
33 | * the MultiLog should remove this channel from the list and delete it. | ||
34 | */ | ||
35 | virtual bool append( MultiLog::LogEntry *pEntry ) = 0; | ||
36 | |||
37 | /** | ||
38 | * Should perform any operations that need to take place in order to safely | ||
39 | * close and cleanup the log. | ||
40 | *@returns True means that everything can go as planned. False means that | ||
41 | * the MultiLog should remove this channel from the list and delete it. | ||
42 | */ | ||
43 | virtual bool closeLog() = 0; | ||
44 | }; | ||
45 | |||
46 | #endif | ||
diff --git a/src/multilogtext.cpp b/src/multilogtext.cpp new file mode 100644 index 0000000..be64595 --- /dev/null +++ b/src/multilogtext.cpp | |||
@@ -0,0 +1,152 @@ | |||
1 | |||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <fcntl.h> | ||
5 | #include <unistd.h> | ||
6 | #include <time.h> | ||
7 | #include <string.h> | ||
8 | #include "multilogtext.h" | ||
9 | |||
10 | MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat ) | ||
11 | { | ||
12 | this->lpFormat = NULL; | ||
13 | nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); | ||
14 | setLogFormat( lpFormat ); | ||
15 | } | ||
16 | |||
17 | MultiLogText::MultiLogText( int nFileDesc, const char *lpFormat ) | ||
18 | { | ||
19 | this->lpFormat = NULL; | ||
20 | nFD = nFileDesc; | ||
21 | setLogFormat( lpFormat ); | ||
22 | } | ||
23 | |||
24 | MultiLogText::~MultiLogText() | ||
25 | { | ||
26 | if( nFD != -1 ) | ||
27 | { | ||
28 | close( nFD ); | ||
29 | } | ||
30 | |||
31 | delete[] lpFormat; | ||
32 | } | ||
33 | |||
34 | bool MultiLogText::setLogFormat( const char *lpFormat ) | ||
35 | { | ||
36 | char buf[200]; | ||
37 | int k = 0; | ||
38 | static char fmts[10][4]={ | ||
39 | {'y', 'd', '0', '1'}, | ||
40 | {'m', 'd', '0', '2'}, | ||
41 | {'d', 'd', '0', '3'}, | ||
42 | {'h', 'd', '0', '4'}, | ||
43 | {'M', 'd', '0', '5'}, | ||
44 | {'s', 'd', '0', '6'}, | ||
45 | {'l', 'd', '0', '7'}, | ||
46 | {'f', 's', '0', '8'}, | ||
47 | {'L', 'd', '0', '9'}, | ||
48 | {'t', 's', '1', '0'}, | ||
49 | }; | ||
50 | |||
51 | for( int j = 0; lpFormat[j] != '\0'; j++ ) | ||
52 | { | ||
53 | if( lpFormat[j] == '%' ) | ||
54 | { | ||
55 | buf[k++] = '%'; | ||
56 | int nPlace = k++; | ||
57 | k++; | ||
58 | buf[k++] = '$'; | ||
59 | bool bDone = false; | ||
60 | for( j++; bDone == false; j++ ) | ||
61 | { | ||
62 | int l; | ||
63 | for( l = 0; l < 10; l++ ) | ||
64 | { | ||
65 | if( lpFormat[j] == fmts[l][0] ) | ||
66 | { | ||
67 | buf[nPlace] = fmts[l][2]; | ||
68 | buf[nPlace+1] = fmts[l][3]; | ||
69 | buf[k++] = fmts[l][1]; | ||
70 | bDone = true; | ||
71 | break; | ||
72 | } | ||
73 | } | ||
74 | if( l == 10 ) | ||
75 | { | ||
76 | buf[k++] = lpFormat[j]; | ||
77 | } | ||
78 | } | ||
79 | j--; | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | buf[k++] = lpFormat[j]; | ||
84 | } | ||
85 | } | ||
86 | buf[k++] = '\n'; | ||
87 | buf[k] = '\0'; | ||
88 | |||
89 | if( this->lpFormat != NULL ) | ||
90 | { | ||
91 | delete[] this->lpFormat; | ||
92 | } | ||
93 | this->lpFormat = new char[k+1]; | ||
94 | strcpy( this->lpFormat, buf ); | ||
95 | |||
96 | return true; | ||
97 | } | ||
98 | |||
99 | bool MultiLogText::openLog() | ||
100 | { | ||
101 | if( nFD == -1 ) | ||
102 | { | ||
103 | return false; | ||
104 | } | ||
105 | return true; | ||
106 | } | ||
107 | |||
108 | bool MultiLogText::append( MultiLog::LogEntry *pEntry ) | ||
109 | { | ||
110 | if( nFD == -1 ) | ||
111 | { | ||
112 | return false; | ||
113 | } | ||
114 | |||
115 | char *line = NULL; | ||
116 | struct tm *pTime; | ||
117 | pTime = localtime( &pEntry->xTime ); | ||
118 | asprintf( | ||
119 | &line, | ||
120 | lpFormat, | ||
121 | pTime->tm_year+1900, | ||
122 | pTime->tm_mon+1, | ||
123 | pTime->tm_mday, | ||
124 | pTime->tm_hour, | ||
125 | pTime->tm_min, | ||
126 | pTime->tm_sec, | ||
127 | pEntry->nLevel, | ||
128 | pEntry->lpFile, | ||
129 | pEntry->nLine, | ||
130 | pEntry->lpText | ||
131 | ); | ||
132 | write( nFD, line, strlen(line) ); | ||
133 | free( line ); | ||
134 | |||
135 | return true; | ||
136 | } | ||
137 | |||
138 | bool MultiLogText::closeLog() | ||
139 | { | ||
140 | if( nFD == -1 ) | ||
141 | { | ||
142 | return false; | ||
143 | } | ||
144 | // Don't close it if it's sdtout or errorout | ||
145 | if( nFD > 2 ) | ||
146 | { | ||
147 | close( nFD ); | ||
148 | } | ||
149 | nFD = -1; | ||
150 | return true; | ||
151 | } | ||
152 | |||
diff --git a/src/multilogtext.h b/src/multilogtext.h new file mode 100644 index 0000000..aa32405 --- /dev/null +++ b/src/multilogtext.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef MULTILOGTEXT_H | ||
2 | #define MULTILOGTEXT_H | ||
3 | |||
4 | #include "multilogchannel.h" | ||
5 | |||
6 | /** | ||
7 | * Simple MultiLogChannel that takes the logdata, formats it textually, and | ||
8 | * writes it to a text device, either a file or the screen, yay! This takes | ||
9 | * the place of the old standard logging facility. | ||
10 | * The entries in the format follow the standard printf % style, and are as | ||
11 | * follows: | ||
12 | * <ul> | ||
13 | * <li>%y - current year</li> | ||
14 | * <li>%m - current month</li> | ||
15 | * <li>%d - current day</li> | ||
16 | * <li>%h - current hour (24-hour format)</li> | ||
17 | * <li>%M - current minute</li> | ||
18 | * <li>%s - current seccond</li> | ||
19 | * <li>%l - Loglevel (numerical)</li> | ||
20 | * <li>%f - Filename</li> | ||
21 | * <li>%L - Line number</li> | ||
22 | * <li>%t - Full text of the log entry</li> | ||
23 | * </ul> | ||
24 | *@author Mike Buland | ||
25 | */ | ||
26 | class MultiLogText : public MultiLogChannel | ||
27 | { | ||
28 | public: | ||
29 | /** | ||
30 | * Construct a MultiLogText object around a specific filename and format. | ||
31 | * The file named by sFileName will be opened for writting in text+append | ||
32 | * mode. No existing data will be destroyed. | ||
33 | *@param sFileName The file to output log-data to. | ||
34 | *@param lpFormat The format using the above specifications to be used for | ||
35 | * every log entry. | ||
36 | */ | ||
37 | MultiLogText( const char *sFileName, const char *lpFormat ); | ||
38 | |||
39 | /** | ||
40 | * Construct a MultiLogText object around a specific file and format. | ||
41 | * The file descriptor passed in should describe an already opened and set- | ||
42 | * up file or device. This could easily be a socket or stdout or stderr. | ||
43 | *@param nFileDesc The already opened descriptor to send data to. | ||
44 | *@param lpFormat The format using the above specifications to be used for | ||
45 | * every log entry. | ||
46 | */ | ||
47 | MultiLogText( int nFileDesc, const char *lpFormat ); | ||
48 | |||
49 | /** | ||
50 | * Destroy the object. | ||
51 | */ | ||
52 | ~MultiLogText(); | ||
53 | |||
54 | bool openLog(); | ||
55 | bool append( MultiLog::LogEntry *pEntry ); | ||
56 | bool closeLog(); | ||
57 | |||
58 | /** | ||
59 | * Change the log format on the fly. | ||
60 | *@param lpFormat The new format to use for all future log entries. | ||
61 | *@returns True if everything was fine, false for catastrophic failure. | ||
62 | */ | ||
63 | bool setLogFormat( const char *lpFormat ); | ||
64 | |||
65 | private: | ||
66 | int nFD; /**< The file descriptor we're writing to. */ | ||
67 | char *lpFormat; /**< The format that we're using, converted for printf. */ | ||
68 | }; | ||
69 | |||
70 | #endif | ||
diff --git a/src/pproc.cpp b/src/pproc.cpp new file mode 100644 index 0000000..f5cb869 --- /dev/null +++ b/src/pproc.cpp | |||
@@ -0,0 +1,60 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include "pproc.h" | ||
4 | |||
5 | void processParams( int argc, char *argv[], PPROC *pproc ) | ||
6 | { | ||
7 | // Loop over all the params except the first, no params, no looping! | ||
8 | for( int j = 1; j < argc; j++ ) | ||
9 | { | ||
10 | //printf("Param[%d]: \"%s\"\n", j, argv[j] ); | ||
11 | if( argv[j][0] == '-' ) | ||
12 | { | ||
13 | if( argv[j][1] == '-' ) | ||
14 | { | ||
15 | // Proccess a long-word param string | ||
16 | for( int k = 0; | ||
17 | pproc[k].proc != NULL || pproc[k].stateVar != NULL; | ||
18 | k++ ) | ||
19 | { | ||
20 | if( !strcmp( pproc[k].lpWord, &argv[j][2] ) ) | ||
21 | { | ||
22 | if( pproc[k].proc != NULL ) | ||
23 | { | ||
24 | j += pproc[k].proc( argc-j, &argv[j] ); | ||
25 | } | ||
26 | if( pproc[k].stateVar != NULL ) | ||
27 | { | ||
28 | (*(pproc[k].stateVar)) = pproc[k].bSetState; | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | else | ||
34 | { | ||
35 | // Process a one char param string | ||
36 | for( int k = 0; | ||
37 | pproc[k].proc != NULL || pproc[k].stateVar != NULL; | ||
38 | k++ ) | ||
39 | { | ||
40 | if( pproc[k].cChar == argv[j][1] ) | ||
41 | { | ||
42 | if( pproc[k].proc != NULL ) | ||
43 | { | ||
44 | j += pproc[k].proc( argc-j, &argv[j] ); | ||
45 | } | ||
46 | if( pproc[k].stateVar != NULL ) | ||
47 | { | ||
48 | (*(pproc[k].stateVar)) = pproc[k].bSetState; | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | else | ||
55 | { | ||
56 | // Handle generic params here. | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
diff --git a/src/pproc.h b/src/pproc.h new file mode 100644 index 0000000..bf5063c --- /dev/null +++ b/src/pproc.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef PPROC_H_ | ||
2 | #define PPROC_H_ | ||
3 | |||
4 | /** | ||
5 | * Contains all required info to handle a single program parameter. | ||
6 | *@author Mike Buland | ||
7 | */ | ||
8 | typedef struct PPROC | ||
9 | { | ||
10 | const char *lpWord; /**< The full text-word to use as a param. */ | ||
11 | const char cChar; /**< The short char version of the param. */ | ||
12 | /** | ||
13 | * Pointer to the function to call when this param is triggered. | ||
14 | *@param argc The number of params after and including the one that | ||
15 | * triggered this call. | ||
16 | *@param argv The array of commandline tokens to use as parameters. | ||
17 | *@returns 0 for everything is ok. A number greater than zero signals that | ||
18 | * this parameter function used n parameters and they should be skipped by | ||
19 | * the processParams function. | ||
20 | */ | ||
21 | int (*proc)( int argc, char *argv[] ); | ||
22 | bool *stateVar; /**< A pointer to a bool to be setwhen this is triggered */ | ||
23 | bool bSetState; /**< The state to set the above bool to. */ | ||
24 | } PPROC; | ||
25 | |||
26 | /** | ||
27 | * Process command line parameters based on a null-terminated array of PPROC | ||
28 | * structures. | ||
29 | *@param argc Should come straight from your main function's argc. | ||
30 | *@param argv Should come straight from your main function's argv. | ||
31 | *@param pproc The array of params that this function can respond to. | ||
32 | */ | ||
33 | void processParams( int argc, char *argv[], PPROC *pproc ); | ||
34 | |||
35 | #endif /*PPROC_H_*/ | ||
diff --git a/src/pqueue.cpp b/src/pqueue.cpp new file mode 100644 index 0000000..1f0b8b5 --- /dev/null +++ b/src/pqueue.cpp | |||
@@ -0,0 +1,33 @@ | |||
1 | #include "pqueue.h" | ||
2 | |||
3 | PQueue::PQueue( int nNewNumQueues ) | ||
4 | { | ||
5 | nNumQueues = nNewNumQueues; | ||
6 | aQueue = new Queue[nNumQueues]; | ||
7 | } | ||
8 | |||
9 | PQueue::~PQueue() | ||
10 | { | ||
11 | delete[] aQueue; | ||
12 | } | ||
13 | |||
14 | void PQueue::enqueue( void *pData, int nQueueLevel ) | ||
15 | { | ||
16 | if( nQueueLevel < 0 || nQueueLevel >= nNumQueues ) | ||
17 | return; | ||
18 | |||
19 | aQueue[nQueueLevel].enqueue( pData ); | ||
20 | } | ||
21 | |||
22 | void *PQueue::dequeue() | ||
23 | { | ||
24 | for( int j = 0; j < nNumQueues; j++ ) | ||
25 | { | ||
26 | if( aQueue[j].isEmpty() == false ) | ||
27 | { | ||
28 | return aQueue[j].dequeue(); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | return NULL; | ||
33 | } | ||
diff --git a/src/pqueue.h b/src/pqueue.h new file mode 100644 index 0000000..1b45f75 --- /dev/null +++ b/src/pqueue.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef PQUEUE_H | ||
2 | #define PQUEUE_H | ||
3 | |||
4 | #include "queue.h" | ||
5 | |||
6 | /** Priority queue. This is just like a queue, but something with a higher | ||
7 | * priority will always come off the queue before something with a lower | ||
8 | * priority, even if it's added after. Otherwise works just like a queue. | ||
9 | *@author Mike Buland | ||
10 | */ | ||
11 | class PQueue | ||
12 | { | ||
13 | public: | ||
14 | /** Create a queue with any number of different priorities. | ||
15 | *@param nNewNumQueues The number of queues, the default is 3 | ||
16 | */ | ||
17 | PQueue( int nNewNumQueues=3 ); | ||
18 | |||
19 | /** | ||
20 | * Cleanup all contained queues. | ||
21 | */ | ||
22 | ~PQueue(); | ||
23 | |||
24 | /** Add a new item to the queue at the specified priority. A lower | ||
25 | * number means a higher priority! | ||
26 | *@param pData A pointer to the data to add to the queue | ||
27 | *@param nQueueLevel The priority to set the new data to | ||
28 | */ | ||
29 | void enqueue( void *pData, int nQueueLevel ); | ||
30 | |||
31 | /** Pull the next item off the queue, high priority first. | ||
32 | *@returns A pointer to the data that was next in the priority queue | ||
33 | */ | ||
34 | void *dequeue(); | ||
35 | |||
36 | private: | ||
37 | /** | ||
38 | * The queues we use for real data storage. | ||
39 | */ | ||
40 | Queue *aQueue; | ||
41 | |||
42 | /** | ||
43 | * The number of priorities or queus that we need. | ||
44 | */ | ||
45 | int nNumQueues; | ||
46 | }; | ||
47 | |||
48 | #endif | ||
diff --git a/src/programchain.cpp b/src/programchain.cpp new file mode 100644 index 0000000..4e53ac8 --- /dev/null +++ b/src/programchain.cpp | |||
@@ -0,0 +1,113 @@ | |||
1 | /*************************************************************************** | ||
2 | programchain.cpp - description | ||
3 | ------------------- | ||
4 | begin : Sat Sep 6 2003 | ||
5 | copyright : (C) 2003 by Mike Buland | ||
6 | email : eichlan@yf-soft.com | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include <stdlib.h> | ||
19 | #include "programchain.h" | ||
20 | |||
21 | ProgramChain::ProgramChain() | ||
22 | { | ||
23 | pLog = MultiLog::getLog(); | ||
24 | pLog->LineLog( MultiLog::LStatus, "Program Chain Initialized." ); | ||
25 | } | ||
26 | |||
27 | ProgramChain::~ProgramChain() | ||
28 | { | ||
29 | } | ||
30 | |||
31 | bool ProgramChain::addLink( ProgramLink *pLink ) | ||
32 | { | ||
33 | if( pLink->init() == false ) | ||
34 | { | ||
35 | emergencyShutdown(); | ||
36 | return false; | ||
37 | } | ||
38 | |||
39 | lLink.append( pLink ); | ||
40 | |||
41 | pLink->setChain( this ); | ||
42 | |||
43 | return true; | ||
44 | } | ||
45 | |||
46 | ProgramLink *ProgramChain::getLink( const char *lpName ) | ||
47 | { | ||
48 | char a; | ||
49 | a = lpName[0]; | ||
50 | return NULL; | ||
51 | } | ||
52 | |||
53 | ProgramLink *ProgramChain::getBaseLink() | ||
54 | { | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | bool ProgramChain::execChainOnce() | ||
59 | { | ||
60 | int nLen = lLink.getSize(); | ||
61 | for( int j = 0; j < nLen; j++ ) | ||
62 | { | ||
63 | if( ((ProgramLink *)lLink[j])->timeSlice() == false ) | ||
64 | { | ||
65 | pLog->LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); | ||
66 | emergencyShutdown(); | ||
67 | return false; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | return true; | ||
72 | } | ||
73 | |||
74 | bool ProgramChain::enterChainLoop() | ||
75 | { | ||
76 | for(;;) | ||
77 | { | ||
78 | if( execChainOnce() == false ) | ||
79 | { | ||
80 | return false; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | return true; | ||
85 | } | ||
86 | |||
87 | void ProgramChain::emergencyShutdown() | ||
88 | { | ||
89 | int nLen = lLink.getSize(); | ||
90 | for( int j = 0; j < nLen; j++ ) | ||
91 | { | ||
92 | ((ProgramLink *)lLink[j])->deInit(); | ||
93 | delete (ProgramLink *)lLink[j]; | ||
94 | } | ||
95 | lLink.empty(); | ||
96 | } | ||
97 | |||
98 | LinkMessage *ProgramChain::broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ) | ||
99 | { | ||
100 | int nLen = lLink.getSize(); | ||
101 | for( int j = 0; j < nLen; j++ ) | ||
102 | { | ||
103 | LinkMessage *pMsg = ((ProgramLink *)lLink[j])->processIRM( pMsgOut ); | ||
104 | if( pMsg != NULL ) | ||
105 | { | ||
106 | delete pMsgOut; | ||
107 | return pMsg; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | delete pMsgOut; | ||
112 | return NULL; | ||
113 | } | ||
diff --git a/src/programchain.h b/src/programchain.h new file mode 100644 index 0000000..34f64f8 --- /dev/null +++ b/src/programchain.h | |||
@@ -0,0 +1,88 @@ | |||
1 | #ifndef PROGRAMCHAIN_H | ||
2 | #define PROGRAMCHAIN_H | ||
3 | |||
4 | #include "linkedlist.h" | ||
5 | #include "multilog.h" | ||
6 | #include "programlink.h" | ||
7 | |||
8 | /** The Program Chain links together program "chunks" to more easily facilitate | ||
9 | * a generalized program loop with modular extensions. | ||
10 | *@author Mike Buland | ||
11 | */ | ||
12 | class ProgramChain | ||
13 | { | ||
14 | public: | ||
15 | /** | ||
16 | * Construct an empty chain. | ||
17 | */ | ||
18 | ProgramChain(); | ||
19 | |||
20 | /** | ||
21 | * Destroy your chain. | ||
22 | */ | ||
23 | ~ProgramChain(); | ||
24 | |||
25 | /** Adds a link to the end of the chain. | ||
26 | *@param pLink A pointer to the link to add to the chain. | ||
27 | *@returns True if adding the link was successful, otherwise false | ||
28 | *@author Mike Buland | ||
29 | */ | ||
30 | bool addLink( ProgramLink *pLink ); | ||
31 | |||
32 | /** Gets a link by name. | ||
33 | *@param lpName The name of the link you're looking for. Every link has a | ||
34 | * name, apparently. | ||
35 | *@returns A pointer to the specified ProgramLink, or NULL if none were found | ||
36 | * matching your criteria. | ||
37 | *@author Mike Buland | ||
38 | */ | ||
39 | class ProgramLink *getLink( const char *lpName ); | ||
40 | |||
41 | /** Gets the very first link in the chain. | ||
42 | *@returns A pointer to the first link in the chain. | ||
43 | *@author Mike Buland | ||
44 | */ | ||
45 | class ProgramLink *getBaseLink(); | ||
46 | |||
47 | /** Runs through the chain once. Useful if you want to have more control over | ||
48 | * the operation of the chain. | ||
49 | *@returns true if every link returned true. If at least one link returns false, | ||
50 | * then returns false. | ||
51 | *@author Mike Buland | ||
52 | */ | ||
53 | bool execChainOnce(); | ||
54 | |||
55 | /** Enters the master chain loop, looping over the entire chain and executing | ||
56 | * every link's TimeSlice routine in order, over and over, until a link returns | ||
57 | * a false value. | ||
58 | *@returns False, always. It returns true unless a link returned false, but loops | ||
59 | * until a link does return false. | ||
60 | *@author Mike Buland | ||
61 | **/ | ||
62 | bool enterChainLoop(); | ||
63 | |||
64 | /** Broadcasts an Immediate Response Message to all active links, save the | ||
65 | * sender. Whatever link first responds with a non-null response message | ||
66 | * will have it's messages sent back to the broadcasting link as the returns | ||
67 | * of this function call. Therefore it is very important that all message | ||
68 | * processing code is handled in a fairly timely fasion. | ||
69 | *@param pMsgOut The message to broadcast in hopes of a response. | ||
70 | *@param pSender The message that sent out the message and doesn't want to | ||
71 | * receive it's own message. This should always just be "this". | ||
72 | *@returns The message that was returned by the first link to return a | ||
73 | * non-null response. If all messages return null responses then this also | ||
74 | * returns null. Please note that whoever calls this will be responsible | ||
75 | * for deleting the message returned by it, if non-null. | ||
76 | */ | ||
77 | class LinkMessage *broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ); | ||
78 | |||
79 | private: | ||
80 | /** | ||
81 | * Shuts down all operation no matter what point in the operation we were. | ||
82 | */ | ||
83 | void emergencyShutdown(); | ||
84 | MultiLog *pLog; /**< A pointer to a log. */ | ||
85 | LinkedList lLink; /**< The linked list that contains all of the links. */ | ||
86 | }; | ||
87 | |||
88 | #endif | ||
diff --git a/src/programlink.cpp b/src/programlink.cpp new file mode 100644 index 0000000..de13be8 --- /dev/null +++ b/src/programlink.cpp | |||
@@ -0,0 +1,71 @@ | |||
1 | /*************************************************************************** | ||
2 | programlink.cpp - description | ||
3 | ------------------- | ||
4 | begin : Sat Sep 6 2003 | ||
5 | copyright : (C) 2003 by Mike Buland | ||
6 | email : eichlan@yf-soft.com | ||
7 | ***************************************************************************/ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * * | ||
11 | * This program is free software; you can redistribute it and/or modify * | ||
12 | * it under the terms of the GNU General Public License as published by * | ||
13 | * the Free Software Foundation; either version 2 of the License, or * | ||
14 | * (at your option) any later version. * | ||
15 | * * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #include "programlink.h" | ||
19 | #include "programchain.h" | ||
20 | |||
21 | ProgramLink::ProgramLink() | ||
22 | { | ||
23 | } | ||
24 | |||
25 | ProgramLink::~ProgramLink() | ||
26 | { | ||
27 | } | ||
28 | |||
29 | LinkMessage *ProgramLink::sendIRM( LinkMessage *pMsgOut ) | ||
30 | { | ||
31 | return pChain->broadcastIRM( pMsgOut, this ); | ||
32 | } | ||
33 | |||
34 | void ProgramLink::setChain( ProgramChain *pNewChain ) | ||
35 | { | ||
36 | pChain = pNewChain; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | void ProgramLink::postMessage( LinkMessage *pMsg, int nLvl ) | ||
41 | { | ||
42 | if( nLvl == msgToChain ) | ||
43 | { | ||
44 | qMsgToChain.enqueue( pMsg ); | ||
45 | } | ||
46 | else if( nLvl == msgToLink ) | ||
47 | { | ||
48 | qMsgToLink.enqueue( pMsg ); | ||
49 | } | ||
50 | else | ||
51 | { | ||
52 | // ERROR! | ||
53 | } | ||
54 | } | ||
55 | |||
56 | LinkMessage *ProgramLink::getMessage( int nLvl ) | ||
57 | { | ||
58 | if( nLvl == msgToChain ) | ||
59 | { | ||
60 | return (LinkMessage *)qMsgToChain.dequeue(); | ||
61 | } | ||
62 | else if( nLvl == msgToLink ) | ||
63 | { | ||
64 | return (LinkMessage *)qMsgToLink.dequeue(); | ||
65 | } | ||
66 | else | ||
67 | { | ||
68 | // ERROR! | ||
69 | } | ||
70 | } | ||
71 | */ | ||
diff --git a/src/programlink.h b/src/programlink.h new file mode 100644 index 0000000..6499fc2 --- /dev/null +++ b/src/programlink.h | |||
@@ -0,0 +1,99 @@ | |||
1 | #ifndef PROGRAMLINK_H | ||
2 | #define PROGRAMLINK_H | ||
3 | |||
4 | class ProgramLink; | ||
5 | #include "queue.h" | ||
6 | #include "linkmessage.h" | ||
7 | #include "programchain.h" | ||
8 | |||
9 | /** | ||
10 | * Program Link is the base class for any object that will be a piece of the | ||
11 | * main program chain loop. | ||
12 | *@author Mike Buland | ||
13 | */ | ||
14 | class ProgramLink | ||
15 | { | ||
16 | friend class ProgramChain; | ||
17 | public: | ||
18 | /** | ||
19 | * Construct a program link. | ||
20 | */ | ||
21 | ProgramLink(); | ||
22 | |||
23 | /** | ||
24 | * Deconstruct. | ||
25 | */ | ||
26 | virtual ~ProgramLink(); | ||
27 | |||
28 | /** | ||
29 | * Initialization code required for a link that wasn't performed in the | ||
30 | * constructor. | ||
31 | *@returns true if initialization was successful. A false value will halt | ||
32 | * the chain. | ||
33 | */ | ||
34 | virtual bool init()=0; | ||
35 | |||
36 | /** | ||
37 | * DeInitialization code that should happen, but doesn't belong in the | ||
38 | * destructor. | ||
39 | *@returns true means everything worked, false means failure, but is | ||
40 | * meaningless. | ||
41 | */ | ||
42 | virtual bool deInit()=0; | ||
43 | |||
44 | /** | ||
45 | * Executed once per link per chain pass. Contains the guts of the program. | ||
46 | *@returns true if everything went well. A false value will halt the chain. | ||
47 | */ | ||
48 | virtual bool timeSlice()=0; | ||
49 | |||
50 | /** | ||
51 | * This must be handled in order to process Instant Response Messages. | ||
52 | * This function should return null on all messages that it doesn't | ||
53 | * understand how to handle, and construct new messages to return to sender | ||
54 | * in the cases where it does understand. | ||
55 | *@param pMsgIn The message that must be processed. | ||
56 | *@returns Either a new message in cases where a response is required, | ||
57 | * or null if nothing needs to be done by this link. | ||
58 | */ | ||
59 | virtual LinkMessage *processIRM( LinkMessage *pMsgIn ) = 0; | ||
60 | |||
61 | /** | ||
62 | * Broadcast a LinkMessage to all other links in the system. Each other | ||
63 | * link will get a call of their processIRM function. If the message gets | ||
64 | * a response then you will regain control immediately, otherwise the system | ||
65 | * will give all other Links a chance to respond before returning NULL. | ||
66 | *@param pMsgOut The message to broadcast. | ||
67 | *@returns The message response, or NULL if no Link understood your message. | ||
68 | */ | ||
69 | LinkMessage *sendIRM( LinkMessage *pMsgOut ); | ||
70 | |||
71 | private: | ||
72 | /** | ||
73 | * Set which chain we're assosiated with. This is hope IRM messages make | ||
74 | * it out to the rest of the world. | ||
75 | *@param pNewChain A pointer to the containing program chain. | ||
76 | */ | ||
77 | void setChain( class ProgramChain *pNewChain ); | ||
78 | |||
79 | /** | ||
80 | * The pointer to the containing chain. | ||
81 | */ | ||
82 | class ProgramChain *pChain; | ||
83 | /* | ||
84 | void postMessage( LinkMessage *pMsg, int nLvl ); | ||
85 | LinkMessage *getMessage( int nLvl ); | ||
86 | |||
87 | enum | ||
88 | { | ||
89 | msgToChain, | ||
90 | msgToLink | ||
91 | }; | ||
92 | |||
93 | private: | ||
94 | Queue qMsgToChain; | ||
95 | Queue qMsgToLink; | ||
96 | */ | ||
97 | }; | ||
98 | |||
99 | #endif | ||
diff --git a/src/protocol.cpp b/src/protocol.cpp new file mode 100644 index 0000000..1b2621f --- /dev/null +++ b/src/protocol.cpp | |||
@@ -0,0 +1,31 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2003 by Mike Buland * | ||
3 | * eichlan@yf-soft.com * | ||
4 | * * | ||
5 | * This program is free software; you can redistribute it and/or modify * | ||
6 | * it under the terms of the GNU General Public License as published by * | ||
7 | * the Free Software Foundation; either version 2 of the License, or * | ||
8 | * (at your option) any later version. * | ||
9 | ***************************************************************************/ | ||
10 | #include "protocol.h" | ||
11 | |||
12 | Protocol::Protocol() | ||
13 | { | ||
14 | pConnection = NULL; | ||
15 | } | ||
16 | |||
17 | Protocol::~Protocol() | ||
18 | { | ||
19 | } | ||
20 | |||
21 | void Protocol::setConnection( Connection *pNewConnection ) | ||
22 | { | ||
23 | pConnection = pNewConnection; | ||
24 | |||
25 | onNewConnection(); | ||
26 | } | ||
27 | |||
28 | Connection *Protocol::getConnection() | ||
29 | { | ||
30 | return pConnection; | ||
31 | } | ||
diff --git a/src/protocol.h b/src/protocol.h new file mode 100644 index 0000000..cd18e37 --- /dev/null +++ b/src/protocol.h | |||
@@ -0,0 +1,58 @@ | |||
1 | #ifndef PROTOCOL_H | ||
2 | #define PROTOCOL_H | ||
3 | |||
4 | #include "connection.h" | ||
5 | |||
6 | /** This is the template for a class that handles specialized input and output | ||
7 | * to connections of different types with different protocols. | ||
8 | *@author Mike Buland | ||
9 | */ | ||
10 | class Protocol | ||
11 | { | ||
12 | public: | ||
13 | /** Constructor */ | ||
14 | Protocol(); | ||
15 | /** Deconstructor */ | ||
16 | virtual ~Protocol(); | ||
17 | |||
18 | /** | ||
19 | * Function is called every time there is new data on the line. This is | ||
20 | * called directly from the Connection class to process data. This is not | ||
21 | * called whever there is pending data on the input, but every time new data | ||
22 | * is added to the input buffer. | ||
23 | *@returns True if processing went alright, false if something went wrong, | ||
24 | * I suppose. In truth this value is thrown away right now. | ||
25 | *@todo Either make a return value of false mean something, or make these | ||
26 | * void. | ||
27 | */ | ||
28 | virtual bool onNewData()=0; | ||
29 | |||
30 | /** | ||
31 | * Function is called when there is a new connection. This should only | ||
32 | * happen once per Protocol object, but gives each protocol object a | ||
33 | * chance to perform connection handshaking and initialization at a point | ||
34 | * where they know that they have a handle to an active Connection. | ||
35 | *@returns See onNewData | ||
36 | */ | ||
37 | virtual bool onNewConnection()=0; | ||
38 | |||
39 | /** | ||
40 | * Sets the Protocol's Connection object. This is rather important, and | ||
41 | * handled usually by the ConnectionManager. | ||
42 | *@param pNewConnection The Connection object that this protocol will use to | ||
43 | * deal with the outside world. | ||
44 | */ | ||
45 | void setConnection( class Connection *pNewConnection ); | ||
46 | |||
47 | /** | ||
48 | * Get a pointer to this object's Connection object, or NULL if one was | ||
49 | * never set. If used with the ConnectionManager that should never happen. | ||
50 | *@returns A pointer to the active Connection. | ||
51 | */ | ||
52 | Connection *getConnection(); | ||
53 | |||
54 | private: | ||
55 | class Connection *pConnection; /**< The pointer to the Connection. */ | ||
56 | }; | ||
57 | |||
58 | #endif | ||
diff --git a/src/protocoltelnet.cpp b/src/protocoltelnet.cpp new file mode 100644 index 0000000..7beea5b --- /dev/null +++ b/src/protocoltelnet.cpp | |||
@@ -0,0 +1,315 @@ | |||
1 | #include "protocoltelnet.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | ProtocolTelnet::ProtocolTelnet() | ||
5 | { | ||
6 | nTermType = termUnInited; | ||
7 | bEchoOn = true; | ||
8 | } | ||
9 | |||
10 | ProtocolTelnet::~ProtocolTelnet() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | bool ProtocolTelnet::onNewConnection() | ||
15 | { | ||
16 | Connection *pCon = getConnection(); | ||
17 | |||
18 | pCon->appendOutput( (char)IAC ); | ||
19 | pCon->appendOutput( (char)WILL ); | ||
20 | pCon->appendOutput( (char)SUPPRESSGA ); | ||
21 | |||
22 | pCon->appendOutput( (char)IAC ); | ||
23 | pCon->appendOutput( (char)DO ); | ||
24 | pCon->appendOutput( (char)SUPPRESSGA ); | ||
25 | |||
26 | pCon->appendOutput( (char)IAC ); | ||
27 | pCon->appendOutput( (char)DONT ); | ||
28 | pCon->appendOutput( (char)TERMTYPE ); | ||
29 | |||
30 | // pCon->appendOutput( IAC ); | ||
31 | // pCon->appendOutput( SB ); | ||
32 | // pCon->appendOutput( TERMTYPE ); | ||
33 | // pCon->appendOutput( 1 ); | ||
34 | // pCon->appendOutput( IAC ); | ||
35 | // pCon->appendOutput( SE ); | ||
36 | |||
37 | pCon->appendOutput( (char)IAC ); | ||
38 | pCon->appendOutput( (char)DONT ); | ||
39 | pCon->appendOutput( (char)ECHO ); | ||
40 | |||
41 | pCon->appendOutput( (char)IAC ); | ||
42 | pCon->appendOutput( (char)WILL ); | ||
43 | pCon->appendOutput( (char)ECHO ); | ||
44 | |||
45 | // 255(IAC),251(WILL),3 | ||
46 | } | ||
47 | |||
48 | bool ProtocolTelnet::onNewData() | ||
49 | { | ||
50 | Connection *pCon = getConnection(); | ||
51 | if( !pCon->hasInput() ) | ||
52 | { | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | int nInSize = pCon->getInputAmnt(); | ||
57 | char *lpInStr = (char *)pCon->getInput(); | ||
58 | |||
59 | // Here we interpret the basic commands and un-encapsulate them, so to | ||
60 | // speak. We'll allow this, even if the terminal is in raw mode, we | ||
61 | // just won't send anything in response... | ||
62 | for( int j = 0; j < nInSize; j++ ) | ||
63 | { | ||
64 | switch( (unsigned char)lpInStr[j] ) | ||
65 | { | ||
66 | case '\r': | ||
67 | fbEdited.appendData('\n'); | ||
68 | if( bEchoOn ) pCon->appendOutput("\n\r"); | ||
69 | break; | ||
70 | |||
71 | case '\n': | ||
72 | break; | ||
73 | |||
74 | case '\177': // backspace | ||
75 | if( fbEdited.getLength() > 0 ) | ||
76 | { | ||
77 | fbEdited.usedData( -1 ); // Delete one char from the end | ||
78 | if( bEchoOn ) pCon->appendOutput(ESC "[D"); // Move the cursor back one | ||
79 | if( bEchoOn ) pCon->appendOutput(ESC "[P"); // Delete one character | ||
80 | } | ||
81 | break; | ||
82 | |||
83 | case '\x1B': // escape sequence | ||
84 | if( (unsigned char)lpInStr[j+1] == '[' ) | ||
85 | { | ||
86 | switch( (unsigned char)lpInStr[j+2] ) | ||
87 | { | ||
88 | case 'A': // Up | ||
89 | break; | ||
90 | |||
91 | case 'B': // Down | ||
92 | break; | ||
93 | |||
94 | case 'C': // Right | ||
95 | break; | ||
96 | |||
97 | case 'D': // Left | ||
98 | break; | ||
99 | } | ||
100 | j+=2; | ||
101 | } | ||
102 | break; | ||
103 | |||
104 | case 0: // NOP: No operation | ||
105 | break; | ||
106 | |||
107 | case IAC: // IAC: Interpret as command | ||
108 | switch( lpInStr[j+1] ) | ||
109 | { | ||
110 | case SE: // SE: End of subnegotiation parameters. | ||
111 | break; | ||
112 | |||
113 | case NOP: // NOP: No operation | ||
114 | break; | ||
115 | |||
116 | case DM: // DM: Data mark. Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. | ||
117 | break; | ||
118 | |||
119 | case BRK: // BRK: Break. Indicates that the "break" or "attention" key was hit. | ||
120 | break; | ||
121 | |||
122 | case IP: // IP: Suspend, interrupt or abort the process to which the NVT is connected. | ||
123 | break; | ||
124 | |||
125 | case AO: // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. | ||
126 | break; | ||
127 | |||
128 | case AYT: // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. | ||
129 | break; | ||
130 | |||
131 | case EC: // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. | ||
132 | break; | ||
133 | |||
134 | case EL: // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. | ||
135 | break; | ||
136 | |||
137 | case GA: // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. | ||
138 | break; | ||
139 | |||
140 | case SB: // SB: Subnegotiation of the indicated option follows. | ||
141 | switch( lpInStr[j+2] ) | ||
142 | { | ||
143 | case TERMTYPE: | ||
144 | if( lpInStr[j+3] == 0 ) | ||
145 | { | ||
146 | for( int k = 0; j+4+k < nInSize; k++ ) | ||
147 | { | ||
148 | if( (unsigned char)lpInStr[j+4+k] == IAC && | ||
149 | (unsigned char)lpInStr[j+5+k] == SE ) | ||
150 | { | ||
151 | lpInStr[j+4+k] = 0; | ||
152 | //@TODO: Do something with the term type... | ||
153 | printf("Term type: %s\n", &lpInStr[j+4] ); | ||
154 | j += 5+k; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | else | ||
159 | { | ||
160 | } | ||
161 | break; | ||
162 | |||
163 | default: | ||
164 | //printf("unknown subnegotiation parameters! (%d)\n", lpInStr[j+2] ); | ||
165 | break; | ||
166 | } | ||
167 | break; | ||
168 | |||
169 | case WILL: // WILL: Indicates the desire to begin performing | ||
170 | switch( lpInStr[j+2] ) | ||
171 | { | ||
172 | case SUPPRESSGA: | ||
173 | j += 2; | ||
174 | // pCon->usedInput( 3 ); | ||
175 | break; | ||
176 | |||
177 | case TERMTYPE: | ||
178 | j += 2; | ||
179 | // pCon->usedInput( 3 ); | ||
180 | break; | ||
181 | |||
182 | case ECHO: | ||
183 | j += 2; | ||
184 | // pCon->usedInput( 3 ); | ||
185 | break; | ||
186 | |||
187 | case NAWS: | ||
188 | default: | ||
189 | pCon->appendOutput( (char)ESC[0] ); | ||
190 | pCon->appendOutput( (char)DONT ); | ||
191 | pCon->appendOutput( lpInStr[j+2] ); | ||
192 | //printf("unknown will command used! (%d)\n", lpInStr[j+2] ); | ||
193 | j += 2; | ||
194 | break; | ||
195 | } | ||
196 | break; | ||
197 | |||
198 | case WONT: // WONT: Indicates the refusal to perform | ||
199 | switch( lpInStr[j+2] ) | ||
200 | { | ||
201 | case ECHO: | ||
202 | j += 2; | ||
203 | // pCon->usedInput( 3 ); | ||
204 | break; | ||
205 | |||
206 | default: | ||
207 | //printf("unknown wont command used! (%d)\n", lpInStr[j+2] ); | ||
208 | j += 2; | ||
209 | break; | ||
210 | } | ||
211 | break; | ||
212 | |||
213 | case DO: // DO: Indicates the request that the other party perform | ||
214 | switch( lpInStr[j+2] ) | ||
215 | { | ||
216 | case ECHO: | ||
217 | j += 2; | ||
218 | break; | ||
219 | |||
220 | case SUPPRESSGA: | ||
221 | j += 2; | ||
222 | break; | ||
223 | |||
224 | default: | ||
225 | pCon->appendOutput( (char)ESC[0] ); | ||
226 | pCon->appendOutput( (char)DONT ); | ||
227 | pCon->appendOutput( lpInStr[j+2] ); | ||
228 | //printf("unknown do command used! (%d)\n", lpInStr[j+2] ); | ||
229 | j += 2; | ||
230 | break; | ||
231 | } | ||
232 | // pCon->usedInput( 3 ); | ||
233 | break; | ||
234 | |||
235 | case DONT: // DONT: Indicates the demand that the other party stop performing | ||
236 | switch( lpInStr[j+2] ) | ||
237 | { | ||
238 | case ECHO: | ||
239 | j += 2; | ||
240 | // pCon->usedInput( 3 ); | ||
241 | break; | ||
242 | |||
243 | default: | ||
244 | printf("unknown dont command used! (%d)\n", lpInStr[j+2] ); | ||
245 | j += 2; | ||
246 | break; | ||
247 | } | ||
248 | break; | ||
249 | } | ||
250 | break; | ||
251 | |||
252 | default: | ||
253 | fbEdited.appendData( lpInStr[j] ); | ||
254 | if( bEchoOn ) pCon->appendOutput( lpInStr[j] ); | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | pCon->usedInput( pCon->getInputAmnt() ); | ||
260 | |||
261 | return true; | ||
262 | } | ||
263 | |||
264 | char *ProtocolTelnet::getLine( bool bFullOnly ) | ||
265 | { | ||
266 | int i = fbEdited.findChar('\n'); | ||
267 | |||
268 | if( i < 0 ) | ||
269 | { | ||
270 | if( bFullOnly == false ) | ||
271 | { | ||
272 | i = fbEdited.getLength(); | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | return NULL; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | char *lpStr = new char[i+1]; | ||
281 | strncpy( lpStr, fbEdited.getData(), i ); | ||
282 | lpStr[i] = '\0'; | ||
283 | |||
284 | fbEdited.usedData( i+1 ); | ||
285 | |||
286 | return lpStr; | ||
287 | } | ||
288 | |||
289 | char *ProtocolTelnet::peekLine( bool bFullOnly ) | ||
290 | { | ||
291 | int i = fbEdited.findChar('\n'); | ||
292 | |||
293 | if( i < 0 ) | ||
294 | { | ||
295 | if( bFullOnly == false ) | ||
296 | { | ||
297 | i = fbEdited.getLength(); | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | return NULL; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | char *lpStr = new char[i+1]; | ||
306 | strncpy( lpStr, fbEdited.getData(), i ); | ||
307 | lpStr[i] = '\0'; | ||
308 | |||
309 | return lpStr; | ||
310 | } | ||
311 | |||
312 | void ProtocolTelnet::setEcho( bool bEchoOn ) | ||
313 | { | ||
314 | this->bEchoOn = bEchoOn; | ||
315 | } | ||
diff --git a/src/protocoltelnet.h b/src/protocoltelnet.h new file mode 100644 index 0000000..4b2fb32 --- /dev/null +++ b/src/protocoltelnet.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef PROTOCOLTELNET_H | ||
2 | #define PROTOCOLTELNET_H | ||
3 | |||
4 | #include "protocol.h" | ||
5 | #include "flexbuf.h" | ||
6 | |||
7 | #define ESC "\x1B" /**< A telnet escape code. */ | ||
8 | |||
9 | /** Handles all specialized protocol actions related to the telnet protocol. | ||
10 | * This includes setting modes, non-scrollable regions, and so on. | ||
11 | *@author Mike Buland | ||
12 | */ | ||
13 | class ProtocolTelnet : public Protocol | ||
14 | { | ||
15 | public: | ||
16 | ProtocolTelnet(); | ||
17 | ~ProtocolTelnet(); | ||
18 | |||
19 | bool onNewData(); | ||
20 | bool onNewConnection(); | ||
21 | |||
22 | char *getLine( bool bFullOnly = true ); | ||
23 | char *peekLine( bool bFullOnly = true ); | ||
24 | |||
25 | void setEcho( bool bEchoOn = true ); | ||
26 | |||
27 | enum | ||
28 | { | ||
29 | termUnInited, | ||
30 | termRaw, | ||
31 | termUnknown, | ||
32 | termVT220, | ||
33 | termXTerm | ||
34 | }; | ||
35 | |||
36 | enum | ||
37 | { | ||
38 | SE = 240, // SE: End of subnegotiation parameters. | ||
39 | NOP = 241, // NOP: No operation | ||
40 | DM = 242, // DM: Data mark. Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. | ||
41 | BRK = 243, // BRK: Break. Indicates that the "break" or "attention" key was hit. | ||
42 | IP = 244, // IP: Suspend, interrupt or abort the process to which the NVT is connected. | ||
43 | AO = 245, // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. | ||
44 | AYT = 246, // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. | ||
45 | EC = 247, // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. | ||
46 | EL = 248, // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. | ||
47 | GA = 249, // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. | ||
48 | SB = 250, // SB: Subnegotiation of the indicated option follows. | ||
49 | WILL = 251, // WILL: Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. | ||
50 | WONT = 252, // WONT: Indicates the refusal to perform, or continue performing, the indicated option. | ||
51 | DO = 253, // DO: Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. | ||
52 | DONT = 254, // DONT: Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option. | ||
53 | IAC = 255 // IAC: Interpret as command | ||
54 | }; | ||
55 | |||
56 | enum | ||
57 | { | ||
58 | ECHO = 1, // Explain who'll echo | ||
59 | SUPPRESSGA = 3, // Suppress Go Ahead | ||
60 | TERMTYPE = 24, // Terminal Type | ||
61 | NAWS = 31, // Window size | ||
62 | TERMSPEED = 32, // Terminal Speed | ||
63 | LINEMODE = 34 // Linemode | ||
64 | }; | ||
65 | |||
66 | private: | ||
67 | int nTermType; | ||
68 | |||
69 | int nTermWidth; | ||
70 | int nTermHeight; | ||
71 | |||
72 | FlexBuf fbEdited; | ||
73 | |||
74 | bool bEchoOn; | ||
75 | }; | ||
76 | |||
77 | #endif | ||
diff --git a/src/queue.cpp b/src/queue.cpp new file mode 100644 index 0000000..42999fe --- /dev/null +++ b/src/queue.cpp | |||
@@ -0,0 +1,26 @@ | |||
1 | #include "queue.h" | ||
2 | |||
3 | void Queue::enqueue( void *data ) | ||
4 | { | ||
5 | lQueueData.append( data ); | ||
6 | } | ||
7 | |||
8 | void *Queue::dequeue() | ||
9 | { | ||
10 | void *dat = lQueueData[0]; | ||
11 | if( dat != NULL ) | ||
12 | { | ||
13 | lQueueData.deleteAt( 0 ); | ||
14 | } | ||
15 | return dat; | ||
16 | } | ||
17 | |||
18 | bool Queue::isEmpty() | ||
19 | { | ||
20 | return lQueueData.isEmpty(); | ||
21 | } | ||
22 | |||
23 | void Queue::empty() | ||
24 | { | ||
25 | lQueueData.empty(); | ||
26 | } | ||
diff --git a/src/queue.h b/src/queue.h new file mode 100644 index 0000000..692f5d8 --- /dev/null +++ b/src/queue.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef QUEUE_H | ||
2 | #define QUEUE_H | ||
3 | #include "linkedlist.h" | ||
4 | |||
5 | /** | ||
6 | * An ultra-simple queue implementation. It just uses a linked list as it's | ||
7 | * container so we don't have to worry about anything! | ||
8 | *@author Mike Buland | ||
9 | */ | ||
10 | class Queue | ||
11 | { | ||
12 | public: | ||
13 | /** | ||
14 | * Puts a new item at the end of the queue. | ||
15 | *@param data A new value to put at the end of the queue. | ||
16 | */ | ||
17 | void enqueue( void *data ); | ||
18 | |||
19 | /** | ||
20 | * Gets the begining item of the queue off and returns it. | ||
21 | *@returns The value at the front of the queue. | ||
22 | */ | ||
23 | void *dequeue(); | ||
24 | |||
25 | /** | ||
26 | * Checks if the queueu is empty. | ||
27 | *@returns True if the queueu is empty, and false if it has things in it. | ||
28 | */ | ||
29 | bool isEmpty(); | ||
30 | |||
31 | /** | ||
32 | * Empty the queue. | ||
33 | */ | ||
34 | void empty(); | ||
35 | |||
36 | /** | ||
37 | * Get a pointer to the internal list object. | ||
38 | *@returns A pointer to the internal list object. | ||
39 | */ | ||
40 | LinkedList *getList() { return &lQueueData; }; | ||
41 | |||
42 | private: | ||
43 | LinkedList lQueueData; /**< Where all of the real data is stored. */ | ||
44 | }; | ||
45 | #endif | ||
diff --git a/src/ringlist.cpp b/src/ringlist.cpp new file mode 100644 index 0000000..9efbbc4 --- /dev/null +++ b/src/ringlist.cpp | |||
@@ -0,0 +1,106 @@ | |||
1 | // | ||
2 | // C++ Implementation: ringlist | ||
3 | // | ||
4 | // Description: | ||
5 | // | ||
6 | // | ||
7 | // Author: Mike Buland <eichlan@yf-soft.com>, (C) 2005 | ||
8 | // | ||
9 | // Copyright: See COPYING file that comes with this distribution | ||
10 | // | ||
11 | // | ||
12 | #include <stdlib.h> | ||
13 | |||
14 | #include "ringlist.h" | ||
15 | |||
16 | RingList::RingList( int nInitSize ) | ||
17 | : List() | ||
18 | { | ||
19 | nFirstIndex = 0; | ||
20 | nRealLength = nInitSize; | ||
21 | nDataLength = 0; | ||
22 | apData = new void*[nInitSize]; | ||
23 | pPushBuf = NULL; | ||
24 | } | ||
25 | |||
26 | RingList::~RingList() | ||
27 | { | ||
28 | delete[] apData; | ||
29 | } | ||
30 | |||
31 | void *RingList::getAt( int nIndex ) | ||
32 | { | ||
33 | if( nIndex < 0 || nIndex >= nDataLength ) | ||
34 | { | ||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | return apData[(nFirstIndex+nIndex)%nRealLength]; | ||
39 | } | ||
40 | |||
41 | void RingList::append( void *pData ) | ||
42 | { | ||
43 | int nIndex = (nFirstIndex+nDataLength)%nRealLength; | ||
44 | |||
45 | pPushBuf = apData[nIndex]; | ||
46 | apData[nIndex] = pData; | ||
47 | |||
48 | if( nDataLength == nRealLength ) | ||
49 | { | ||
50 | nFirstIndex = (nFirstIndex+1)%nRealLength; | ||
51 | } | ||
52 | else | ||
53 | { | ||
54 | nDataLength++; | ||
55 | // We really didn't need it this time... | ||
56 | pPushBuf = NULL; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | void RingList::insertBefore( void *pData, int nPos ) | ||
61 | { | ||
62 | // Not implemented right now, don't even try it! | ||
63 | } | ||
64 | |||
65 | int RingList::getSize() | ||
66 | { | ||
67 | return nDataLength; | ||
68 | } | ||
69 | |||
70 | bool RingList::isEmpty() | ||
71 | { | ||
72 | return nDataLength==0; | ||
73 | } | ||
74 | |||
75 | void RingList::deleteAt( int nIndex ) | ||
76 | { | ||
77 | // Also not implemented yet | ||
78 | } | ||
79 | |||
80 | void RingList::empty() | ||
81 | { | ||
82 | nFirstIndex = 0; | ||
83 | nDataLength = 0; | ||
84 | } | ||
85 | |||
86 | void RingList::setSize( int nNewSize ) | ||
87 | { | ||
88 | if( apData ) | ||
89 | { | ||
90 | delete[] apData; | ||
91 | } | ||
92 | nFirstIndex = 0; | ||
93 | nRealLength = nNewSize; | ||
94 | nDataLength = 0; | ||
95 | apData = new void*[nNewSize]; | ||
96 | } | ||
97 | |||
98 | void RingList::setAt( int nIndex, void *pData ) | ||
99 | { | ||
100 | apData[(nIndex+nFirstIndex)%nRealLength] = pData; | ||
101 | } | ||
102 | |||
103 | void *RingList::getPushBuf() | ||
104 | { | ||
105 | return pPushBuf; | ||
106 | } | ||
diff --git a/src/ringlist.h b/src/ringlist.h new file mode 100644 index 0000000..1a4d3a9 --- /dev/null +++ b/src/ringlist.h | |||
@@ -0,0 +1,112 @@ | |||
1 | #ifndef RINGLIST_H | ||
2 | #define RINGLIST_H | ||
3 | |||
4 | #include "list.h" | ||
5 | |||
6 | /** | ||
7 | * A RingList or Ring Buffer implementation. This is a list that never grows in | ||
8 | * size once it is created, but instead once it is full new items added to the | ||
9 | * RingList replace the oldest items and the zero-index is virtually shifted. | ||
10 | * Since no data is actually moved when zero-index moves, this is very | ||
11 | * efficient. | ||
12 | * <br> | ||
13 | * The items removed are not actually deleted by the RingList, so instead they | ||
14 | * are first moved into a temporary "Push Buffer" that can be accessed so that | ||
15 | * elements pushed off the edge of the RingList can be accessed for cleanup. | ||
16 | *@author Mike Buland | ||
17 | */ | ||
18 | class RingList : public List | ||
19 | { | ||
20 | public: | ||
21 | /** | ||
22 | * Construct a RingList with a fixed initial size. This size never changes | ||
23 | * unless setSize is called later during normal operation. | ||
24 | *@param nInitSize The number of elements to allocate. | ||
25 | */ | ||
26 | RingList( int nInitSize ); | ||
27 | |||
28 | /** | ||
29 | * Clean up the data structures, but not the contained elements. | ||
30 | */ | ||
31 | ~RingList(); | ||
32 | |||
33 | /** | ||
34 | * Get an element at the specified index. | ||
35 | *@param nIndex The index of the element to retreive. | ||
36 | *@returns A pointer to the requested element, or NULL if the element is | ||
37 | * not found or not initialized yet. | ||
38 | */ | ||
39 | void *getAt( int nIndex ); | ||
40 | |||
41 | /** | ||
42 | * Append an element to the end of the list, overwriting the begining if | ||
43 | * necesarry. | ||
44 | *@param pData The pointer to append to the RingList. | ||
45 | */ | ||
46 | void append( void *pData ); | ||
47 | |||
48 | /** | ||
49 | * Insert an element before another in the RingList, pushing all after it | ||
50 | * down the list. | ||
51 | *@param pData The data to insert. | ||
52 | *@param nPos The position that new the element should occupy in the list. | ||
53 | */ | ||
54 | void insertBefore( void *pData, int nPos = 0 ); | ||
55 | |||
56 | /** | ||
57 | * Get the size of the array. | ||
58 | */ | ||
59 | int getSize(); | ||
60 | |||
61 | /** | ||
62 | * Is the RingList empty? | ||
63 | *@returns True if it is empty, false otherwise. | ||
64 | */ | ||
65 | bool isEmpty(); | ||
66 | |||
67 | /** | ||
68 | * Delete an element in the list, moving all later elements down one index. | ||
69 | *@param nIndex The index of the element to delete. | ||
70 | */ | ||
71 | void deleteAt( int nIndex ); | ||
72 | |||
73 | /** | ||
74 | * Remove all elements from the RingList. | ||
75 | */ | ||
76 | void empty(); | ||
77 | |||
78 | /** | ||
79 | * Set a new size for the RingList. Be careful with this one, if shrinking | ||
80 | * this may quietly create a memory leak. | ||
81 | *@param nNewSize The new size to set the RingList to. | ||
82 | *@todo Either fix this memory leak somehow or remove this function. | ||
83 | */ | ||
84 | void setSize( int nNewSize ); | ||
85 | |||
86 | /** | ||
87 | * Set a specific element to a new value. | ||
88 | *@param nIndex The zero-based index to change the value of. | ||
89 | *@param pData The data to put at the location specified by nIndex. | ||
90 | */ | ||
91 | void setAt( int nIndex, void *pData ); | ||
92 | |||
93 | /** | ||
94 | * Retrieve the contents of the push buffer. This is the data that is | ||
95 | * pushed off the end of the array if you append data and the list is full. | ||
96 | * This should be checked after every append operation to be sure there | ||
97 | * isn't anything that needs deleting. | ||
98 | *@returns The last value pushed off the RingList, or NULL if nothing was | ||
99 | * pushed off. | ||
100 | */ | ||
101 | void *getPushBuf(); | ||
102 | |||
103 | private: | ||
104 | int nFirstIndex; /**< The index to be translated as zero. */ | ||
105 | int nRealLength; /**< The Amount of storage space available. */ | ||
106 | int nDataLength; /**< The number of elements filled in. */ | ||
107 | void **apData; /**< The actual data storage. */ | ||
108 | void *pPushBuf; /**< The push buffer. */ | ||
109 | |||
110 | }; | ||
111 | |||
112 | #endif | ||
diff --git a/src/stack.cpp b/src/stack.cpp new file mode 100644 index 0000000..8d9565c --- /dev/null +++ b/src/stack.cpp | |||
@@ -0,0 +1,33 @@ | |||
1 | #include "stack.h" | ||
2 | |||
3 | void Stack::push( void *data ) | ||
4 | { | ||
5 | lStackData.append( data ); | ||
6 | } | ||
7 | |||
8 | void *Stack::top() | ||
9 | { | ||
10 | return lStackData.getAt( lStackData.getSize()-1 ); | ||
11 | } | ||
12 | |||
13 | void Stack::pop() | ||
14 | { | ||
15 | lStackData.deleteAt( lStackData.getSize()-1 ); | ||
16 | } | ||
17 | |||
18 | void *Stack::poptop() | ||
19 | { | ||
20 | void *dat = top(); | ||
21 | pop(); | ||
22 | return dat; | ||
23 | } | ||
24 | |||
25 | bool Stack::isEmpty() | ||
26 | { | ||
27 | return lStackData.isEmpty(); | ||
28 | } | ||
29 | |||
30 | void Stack::empty() | ||
31 | { | ||
32 | lStackData.empty(); | ||
33 | } | ||
diff --git a/src/stack.h b/src/stack.h new file mode 100644 index 0000000..30e2a19 --- /dev/null +++ b/src/stack.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef STACK_H | ||
2 | #define STACK_H | ||
3 | #include "linkedlist.h" | ||
4 | |||
5 | /** An ultra-simple stack implementation that just uses a linked list. | ||
6 | *@author Mike Buland | ||
7 | */ | ||
8 | class Stack | ||
9 | { | ||
10 | public: | ||
11 | /** Pushes a new value onto the top of the stack. | ||
12 | *@param data A new value for the stack. | ||
13 | *@author Mike Buland | ||
14 | */ | ||
15 | void push( void *data ); | ||
16 | |||
17 | /** Returns the top value off of the stack, but doesn't remove it from the | ||
18 | * stack. | ||
19 | *@returns The value at the top of the stack. | ||
20 | *@author Mike Buland | ||
21 | */ | ||
22 | void *top(); | ||
23 | |||
24 | /** Pops the top item off of the stack. | ||
25 | *@author Mike Buland | ||
26 | */ | ||
27 | void pop(); | ||
28 | |||
29 | /** Gets the top item off of the stack, pops it off the stack, and returns | ||
30 | * it. | ||
31 | *@returns The value at the top of the stack. | ||
32 | *@author Mike Buland | ||
33 | */ | ||
34 | void *poptop(); | ||
35 | |||
36 | /** Checks if the stack is empty. | ||
37 | *@returns True if the stack is empty, and false if it has things in it. | ||
38 | *@author Mike Buland | ||
39 | */ | ||
40 | bool isEmpty(); | ||
41 | |||
42 | /** Empty the stack. | ||
43 | *@author Mike Buland | ||
44 | */ | ||
45 | void empty(); | ||
46 | |||
47 | private: | ||
48 | LinkedList lStackData; /**< The actual stack data. */ | ||
49 | }; | ||
50 | #endif | ||
diff --git a/src/test/hashtest.cpp b/src/test/hashtest.cpp new file mode 100644 index 0000000..f31a3f8 --- /dev/null +++ b/src/test/hashtest.cpp | |||
@@ -0,0 +1,107 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <iostream> | ||
3 | #include "hashtable.h" | ||
4 | #include "hashfunctioncasestring.h" | ||
5 | |||
6 | int main() | ||
7 | { | ||
8 | const char *names[]={ | ||
9 | "Homer the Great", | ||
10 | "And Maggie Makes Three", | ||
11 | "Bart's Comet", | ||
12 | "Homie The Clown", | ||
13 | "Bart Vs Australia", | ||
14 | "Homer vs Patty and Selma", | ||
15 | "A star is burns", | ||
16 | "Lisa's Wedding", | ||
17 | "Two Dozen and One Greyhounds", | ||
18 | "The PTA Disbands", | ||
19 | "Round Springfield", | ||
20 | "The Springfield connection", | ||
21 | "Lemon of Troy", | ||
22 | "Who Shot Mr. Burns (Pt. 1)", | ||
23 | "Who Shot Mr. Burns (pt. 2)", | ||
24 | "Radioactive Man", | ||
25 | "Home Sweet Homediddly-dum-doodly", | ||
26 | "Bart Sells His Soul", | ||
27 | "Lisa the Vegetarian", | ||
28 | "Treehouse of horror VI", | ||
29 | "King Size Homer", | ||
30 | "Mother Simpson", | ||
31 | "Sideshow Bob's Last Gleaming", | ||
32 | "The Simpson's 138th Show Spectacular", | ||
33 | "Marge Be Not Proud", | ||
34 | "Team Homer", | ||
35 | "Two Bad Neighbors", | ||
36 | "Scenes From the Class Struggle in Springfield", | ||
37 | "Bart the Fink", | ||
38 | "Lisa the Iconoclast", | ||
39 | "Homer the Smithers", | ||
40 | "The Day the Violence Died", | ||
41 | "A Fish Called Selma", | ||
42 | "Bart on the road", | ||
43 | "22 Short Films about Springfield", | ||
44 | "The Curse of the Flying Hellfish", | ||
45 | "Much Apu about Nothing", | ||
46 | "Homerpalooza", | ||
47 | "The Summer of 4 Ft 2", | ||
48 | "Treehouse of Horror VII", | ||
49 | "You Only Move Twice", | ||
50 | "The Homer They Fall", | ||
51 | "Burns Baby Burns", | ||
52 | "Bart After Dark", | ||
53 | "A Millhouse Divided", | ||
54 | "Lisas Date With Destiny", | ||
55 | "Hurricane Neddy", | ||
56 | "The Mysterious Voyage of Our Homer", | ||
57 | "The Springfield Files", | ||
58 | "The Twisted World of Marge Simpson", | ||
59 | "Mountain of Madness", | ||
60 | NULL | ||
61 | }; | ||
62 | |||
63 | HashTable h( new HashFunctionCaseString(), 5, false ); | ||
64 | |||
65 | int j; | ||
66 | printf("Inserting...\n"); | ||
67 | for( j = 0; j < 10; j++ ) | ||
68 | { | ||
69 | h.insert( names[j], (void *)(j+1) ); | ||
70 | h.insert( names[j], (void *)(j+1) ); | ||
71 | printf("Capacity: %d, Size: %d, Load: %f\n", | ||
72 | h.getCapacity(), | ||
73 | h.getSize(), | ||
74 | h.getLoad() | ||
75 | ); | ||
76 | } | ||
77 | |||
78 | for( j = 0; j < 10; j++ ) | ||
79 | { | ||
80 | printf("\"%s\" = %d\n", names[j], (int)h[names[j]] ); | ||
81 | } | ||
82 | |||
83 | printf("\nDeleting some...\n"); | ||
84 | |||
85 | for( int k = 0; k < 7; k++ ) | ||
86 | { | ||
87 | h.del( names[k] ); | ||
88 | //h.insert( names[j], (void *)(j+1) ); | ||
89 | printf("Capacity: %d, Size: %d, Load: %f\n", | ||
90 | h.getCapacity(), | ||
91 | h.getSize(), | ||
92 | h.getLoad() | ||
93 | ); | ||
94 | } | ||
95 | |||
96 | printf("\nInserting more...\n"); | ||
97 | |||
98 | for( ; names[j] != NULL; j++ ) | ||
99 | { | ||
100 | h.insert( names[j], (void *)(j+1) ); | ||
101 | printf("Capacity: %d, Size: %d, Load: %f\n", | ||
102 | h.getCapacity(), | ||
103 | h.getSize(), | ||
104 | h.getLoad() | ||
105 | ); | ||
106 | } | ||
107 | } | ||
diff --git a/src/test/httpsrv/httpconnectionmonitor.cpp b/src/test/httpsrv/httpconnectionmonitor.cpp new file mode 100644 index 0000000..4eb6817 --- /dev/null +++ b/src/test/httpsrv/httpconnectionmonitor.cpp | |||
@@ -0,0 +1,72 @@ | |||
1 | #include "httpconnectionmonitor.h" | ||
2 | #include "http.h" | ||
3 | #include <sys/stat.h> | ||
4 | |||
5 | HttpConnectionMonitor::HttpConnectionMonitor() | ||
6 | { | ||
7 | } | ||
8 | |||
9 | HttpConnectionMonitor::~HttpConnectionMonitor() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | bool HttpConnectionMonitor::onNewConnection( Connection *pCon ) | ||
14 | { | ||
15 | Http hp( pCon ); | ||
16 | |||
17 | pCon->readInput( 60, 0 ); | ||
18 | printf("#######################\n%s\n#######################\n", pCon->getInput() ); | ||
19 | |||
20 | while( hp.parseRequest() == false ); | ||
21 | printf("Done parsing.\n\n"); | ||
22 | |||
23 | if( hp.getRequestType() == Http::reqGet ) | ||
24 | { | ||
25 | printf("\"\"\"%s\"\"\"\n", hp.getRequestURI() ); | ||
26 | if( !strcmp( hp.getRequestURI(), "/" ) ) | ||
27 | { | ||
28 | std::string content("<html><head><title>Server Test</test></head><body>This is a test of a new system where all the pages will be more or less dynamic...<br>If you want to try to login, you can do that here:<br><form method=\"post\" action=\"showvars\" enctype=\"multipart/form-data\">Name: <input type=\"text\" name=\"name\"><br>Password: <input type=\"password\" name=\"pass\"><br><input type=\"submit\" name=\"action\" value=\"login\"></form></body></html>"); | ||
29 | hp.buildResponse(); | ||
30 | hp.setResponseContent( | ||
31 | "text/html", | ||
32 | content.c_str(), | ||
33 | content.size() | ||
34 | ); | ||
35 | hp.sendResponse(); | ||
36 | } | ||
37 | else | ||
38 | { | ||
39 | std::string content("<html><head><title>URL Not Found</test></head><body>There is no content mapped to the URL you requested. Please try another one.</body></html>"); | ||
40 | hp.buildResponse( 404, "File not found."); | ||
41 | hp.setResponseContent( | ||
42 | "text/html", | ||
43 | content.c_str(), | ||
44 | content.size() | ||
45 | ); | ||
46 | hp.sendResponse(); | ||
47 | } | ||
48 | } | ||
49 | else | ||
50 | { | ||
51 | printf("Non get: %s\n", hp.getRequestTypeStr() ); | ||
52 | } | ||
53 | pCon->writeOutput(); | ||
54 | |||
55 | if( pCon->hasInput() ) | ||
56 | { | ||
57 | std::string s( pCon->getInput(), pCon->getInputAmnt() ); | ||
58 | |||
59 | printf("Reamining data\n==============\n%s\n==============\n", | ||
60 | s.c_str() ); | ||
61 | } | ||
62 | |||
63 | pCon->disconnect(); | ||
64 | |||
65 | return true; | ||
66 | } | ||
67 | |||
68 | bool HttpConnectionMonitor::onClosedConnection( Connection *pCon ) | ||
69 | { | ||
70 | return true; | ||
71 | } | ||
72 | |||
diff --git a/src/test/httpsrv/httpconnectionmonitor.h b/src/test/httpsrv/httpconnectionmonitor.h new file mode 100644 index 0000000..63f29e4 --- /dev/null +++ b/src/test/httpsrv/httpconnectionmonitor.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef HTTPCONNECTIONMONITOR_H | ||
2 | #define HTTPCONNECTIONMONITOR_H | ||
3 | |||
4 | #include "connectionmonitor.h" | ||
5 | |||
6 | class HttpConnectionMonitor : public ConnectionMonitor | ||
7 | { | ||
8 | public: | ||
9 | HttpConnectionMonitor(); | ||
10 | ~HttpConnectionMonitor(); | ||
11 | |||
12 | bool onNewConnection( Connection *pCon ); | ||
13 | bool onClosedConnection( Connection *pCon ); | ||
14 | }; | ||
15 | |||
16 | #endif | ||
diff --git a/src/test/httpsrv/main.cpp b/src/test/httpsrv/main.cpp new file mode 100644 index 0000000..4ee1ad3 --- /dev/null +++ b/src/test/httpsrv/main.cpp | |||
@@ -0,0 +1,21 @@ | |||
1 | #include "connectionmanager.h" | ||
2 | #include "httpconnectionmonitor.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | printf("Starting server...\n"); | ||
7 | |||
8 | ConnectionManager srv; | ||
9 | HttpConnectionMonitor http; | ||
10 | |||
11 | srv.setConnectionMonitor( &http ); | ||
12 | |||
13 | srv.startServer( 7331, 40 ); | ||
14 | |||
15 | for(;;) | ||
16 | { | ||
17 | srv.scanConnections( 5000, false ); | ||
18 | } | ||
19 | |||
20 | return 0; | ||
21 | } | ||
diff --git a/src/test/md5test.cpp b/src/test/md5test.cpp new file mode 100644 index 0000000..6f832df --- /dev/null +++ b/src/test/md5test.cpp | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include "md5.h" | ||
4 | |||
5 | int main() | ||
6 | { | ||
7 | md5 mproc; | ||
8 | md5sum sum; | ||
9 | char hexstr[33]; | ||
10 | |||
11 | memset( hexstr, 0, 33 ); | ||
12 | |||
13 | mproc.sumString( &sum, "qwertyuiopasdfgh" ); | ||
14 | mproc.sumToHex( &sum, hexstr ); | ||
15 | printf("sum: %s\n", hexstr ); | ||
16 | printf("chk: 1ebfc043d8880b758b13ddc8aa1638ef\n"); | ||
17 | |||
18 | return 0; | ||
19 | } | ||
diff --git a/src/test/teltest/main.cpp b/src/test/teltest/main.cpp new file mode 100644 index 0000000..ce968c4 --- /dev/null +++ b/src/test/teltest/main.cpp | |||
@@ -0,0 +1,21 @@ | |||
1 | #include "connectionmanager.h" | ||
2 | #include "telnetmonitor.h" | ||
3 | |||
4 | int main() | ||
5 | { | ||
6 | printf("Starting server...\n"); | ||
7 | |||
8 | ConnectionManager srv; | ||
9 | TelnetMonitor telnet; | ||
10 | |||
11 | srv.setConnectionMonitor( &telnet ); | ||
12 | |||
13 | srv.startServer( 4001, 40 ); | ||
14 | |||
15 | for(;;) | ||
16 | { | ||
17 | srv.scanConnections( 5000, false ); | ||
18 | } | ||
19 | |||
20 | return 0; | ||
21 | } | ||
diff --git a/src/test/teltest/telnetmonitor.cpp b/src/test/teltest/telnetmonitor.cpp new file mode 100644 index 0000000..001932f --- /dev/null +++ b/src/test/teltest/telnetmonitor.cpp | |||
@@ -0,0 +1,53 @@ | |||
1 | #include "telnetmonitor.h" | ||
2 | #include "protocoltelnet.h" | ||
3 | #include <sys/stat.h> | ||
4 | |||
5 | TelnetMonitor::TelnetMonitor() | ||
6 | { | ||
7 | } | ||
8 | |||
9 | TelnetMonitor::~TelnetMonitor() | ||
10 | { | ||
11 | } | ||
12 | |||
13 | bool TelnetMonitor::init() | ||
14 | { | ||
15 | return true; | ||
16 | } | ||
17 | |||
18 | bool TelnetMonitor::deInit() | ||
19 | { | ||
20 | return true; | ||
21 | } | ||
22 | |||
23 | bool TelnetMonitor::timeSlice() | ||
24 | { | ||
25 | for( int j = 0; j < lCon.getSize(); j++ ) | ||
26 | { | ||
27 | if( ((Connection *)lCon[j])->hasInput() ) | ||
28 | { | ||
29 | printf("%s\n", ((Connection *)lCon[j])->getInput() ); | ||
30 | } | ||
31 | } | ||
32 | return true; | ||
33 | } | ||
34 | |||
35 | LinkMessage* TelnetMonitor::processIRM( LinkMessage *pMsg ) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | bool TelnetMonitor::onNewConnection( Connection *pCon ) | ||
40 | { | ||
41 | ProtocolTelnet *pt = new ProtocolTelnet(); | ||
42 | pCon->setProtocol( pt ); | ||
43 | |||
44 | lCon.append( pt ); | ||
45 | |||
46 | return true; | ||
47 | } | ||
48 | |||
49 | bool TelnetMonitor::onClosedConnection( Connection *pCon ) | ||
50 | { | ||
51 | return true; | ||
52 | } | ||
53 | |||
diff --git a/src/test/teltest/telnetmonitor.h b/src/test/teltest/telnetmonitor.h new file mode 100644 index 0000000..95c8493 --- /dev/null +++ b/src/test/teltest/telnetmonitor.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef HTTPCONNECTIONMONITOR_H | ||
2 | #define HTTPCONNECTIONMONITOR_H | ||
3 | |||
4 | #include "connectionmonitor.h" | ||
5 | #include "programlink.h" | ||
6 | #include "linkedlist.h" | ||
7 | |||
8 | class TelnetMonitor : public ConnectionMonitor, public ProgramLink | ||
9 | { | ||
10 | public: | ||
11 | TelnetMonitor(); | ||
12 | ~TelnetMonitor(); | ||
13 | |||
14 | bool init(); | ||
15 | bool deInit(); | ||
16 | bool timeSlice(); | ||
17 | LinkMessage* processIRM( LinkMessage *pMsgIn ); | ||
18 | |||
19 | bool onNewConnection( Connection *pCon ); | ||
20 | bool onClosedConnection( Connection *pCon ); | ||
21 | |||
22 | private: | ||
23 | LinkedList lCon; | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/src/test/xmlreadtest.cpp b/src/test/xmlreadtest.cpp new file mode 100644 index 0000000..5fbd021 --- /dev/null +++ b/src/test/xmlreadtest.cpp | |||
@@ -0,0 +1,29 @@ | |||
1 | #include "../xmlfilereader.h" | ||
2 | #include "../xmlstringreader.h" | ||
3 | #include "../xmlfilewriter.h" | ||
4 | |||
5 | int main( int argc, char *argv[] ) | ||
6 | { | ||
7 | if( argc < 4 ) | ||
8 | { | ||
9 | printf("Usage: %s f <file in> <file out>\n", argv[0] ); | ||
10 | printf(" %s s <xml string> <file out>\n\n", argv[0] ); | ||
11 | return 0; | ||
12 | } | ||
13 | |||
14 | if( argv[1][0] == 'f' ) | ||
15 | { | ||
16 | XmlFileReader r( argv[2], true ); | ||
17 | XmlFileWriter w( argv[3], "\t", r.getRoot() ); | ||
18 | w.write(); | ||
19 | //XmlWriter::write( argv[3], r.getRoot(), "\t" ); | ||
20 | } | ||
21 | else if( argv[1][0] == 's' ) | ||
22 | { | ||
23 | XmlStringReader r( argv[2], true ); | ||
24 | //XmlWriter::write( argv[3], r.getRoot(), "\t" ); | ||
25 | } | ||
26 | |||
27 | return 0; | ||
28 | } | ||
29 | |||
diff --git a/src/test/xmlrepltest.cpp b/src/test/xmlrepltest.cpp new file mode 100644 index 0000000..1fe9ec2 --- /dev/null +++ b/src/test/xmlrepltest.cpp | |||
@@ -0,0 +1,31 @@ | |||
1 | #include "xmlwriter.h" | ||
2 | |||
3 | int main() | ||
4 | { | ||
5 | printf("Testing Xml Replacement...\n"); | ||
6 | XmlDocument w; | ||
7 | |||
8 | w.addNode("text"); | ||
9 | w.setContent("this text is before the node. "); | ||
10 | w.addNode("keepme", "This one we keep...", true ); | ||
11 | w.setContent("this text is after."); | ||
12 | w.addNode("deleteme", "This one we don't...", true ); | ||
13 | w.setContent("this is last..." ); | ||
14 | w.closeNode(); | ||
15 | |||
16 | //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); | ||
17 | |||
18 | printf("\n\n"); | ||
19 | |||
20 | XmlNode *xNode = w.getRoot()->detatchNode( 1 ); | ||
21 | |||
22 | //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); | ||
23 | |||
24 | printf("\n\n"); | ||
25 | |||
26 | //XmlWriter::writeNode( stdout, xNode, 0, NULL ); | ||
27 | |||
28 | printf("\n\n"); | ||
29 | |||
30 | return 0; | ||
31 | } | ||
diff --git a/src/test/xmlwritetest.cpp b/src/test/xmlwritetest.cpp new file mode 100644 index 0000000..340c9a3 --- /dev/null +++ b/src/test/xmlwritetest.cpp | |||
@@ -0,0 +1,41 @@ | |||
1 | #include "xmlfilewriter.h" | ||
2 | #include "xmlstringwriter.h" | ||
3 | |||
4 | void fillItIn( XmlWriter &w ) | ||
5 | { | ||
6 | w.addNode("thinglist"); | ||
7 | |||
8 | w.addNode("thing"); | ||
9 | w.addProperty("type", "Weapon"); | ||
10 | |||
11 | w.addNode("id", "Klophin Staff", true ); | ||
12 | w.addNode("name", "Klophin Staff", true ); | ||
13 | w.addNode("durability", "0.01", true ); | ||
14 | w.addNode("size", "0.1", true ); | ||
15 | |||
16 | w.addNode("config"); | ||
17 | w.addNode("damage", "3d6+4", true ); | ||
18 | w.addNode("class", "melee", true ); | ||
19 | w.addNode("type", "bludgeon", true ); | ||
20 | w.addNode("damagedesc", "club/clubs", true ); | ||
21 | w.closeNode(); | ||
22 | |||
23 | w.closeNode(); | ||
24 | |||
25 | w.closeNode(); | ||
26 | } | ||
27 | |||
28 | int main() | ||
29 | { | ||
30 | printf("Testing XmlWriter...\n"); | ||
31 | XmlFileWriter wf("test.xml", "\t"); | ||
32 | |||
33 | fillItIn( wf ); | ||
34 | |||
35 | XmlStringWriter ws("\t"); | ||
36 | fillItIn( ws ); | ||
37 | |||
38 | printf("Now the string version:\n\n%s\n", ws.getString().c_str() ); | ||
39 | |||
40 | return 0; | ||
41 | } | ||
diff --git a/src/tokenstring.cpp b/src/tokenstring.cpp new file mode 100644 index 0000000..0c861ac --- /dev/null +++ b/src/tokenstring.cpp | |||
@@ -0,0 +1,172 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2003 by Mike Buland * | ||
3 | * eichlan@Xagafinelle * | ||
4 | * * | ||
5 | * This program is free software; you can redistribute it and/or modify * | ||
6 | * it under the terms of the GNU General Public License as published by * | ||
7 | * the Free Software Foundation; either version 2 of the License, or * | ||
8 | * (at your option) any later version. * | ||
9 | ***************************************************************************/ | ||
10 | #include "tokenstring.h" | ||
11 | #include <string.h> | ||
12 | |||
13 | TokenString::TokenString( const char *lpNewTokenString ) | ||
14 | { | ||
15 | lpTokenString = NULL; | ||
16 | if( lpNewTokenString ) | ||
17 | { | ||
18 | parseLine( lpNewTokenString ); | ||
19 | } | ||
20 | } | ||
21 | |||
22 | TokenString::~TokenString() | ||
23 | { | ||
24 | delete[] lpTokenString; | ||
25 | for( int j = 0; j < lToken.getSize(); j++ ) | ||
26 | { | ||
27 | delete[] (((Token *)lToken[j])->lpToken); | ||
28 | delete ((Token *)lToken[j]); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | void TokenString::parseLine( const char *lpNewTokenString ) | ||
33 | { | ||
34 | if( lpTokenString != NULL ) | ||
35 | { | ||
36 | delete[] lpTokenString; | ||
37 | lpTokenString = NULL; | ||
38 | for( int j = 0; j < lToken.getSize(); j++ ) | ||
39 | { | ||
40 | delete[] (((Token *)lToken[j])->lpToken); | ||
41 | delete ((Token *)lToken[j]); | ||
42 | } | ||
43 | lToken.empty(); | ||
44 | } | ||
45 | if( lpNewTokenString == NULL ) | ||
46 | { | ||
47 | lpTokenString = new char[1]; | ||
48 | lpTokenString[0] = '\0'; | ||
49 | lToken.setSize(0); | ||
50 | return; | ||
51 | } | ||
52 | // First order of business, make an internal copy so someone can get it | ||
53 | // if they want to. | ||
54 | int nLen = strlen(lpNewTokenString); | ||
55 | lpTokenString = new char[nLen+1]; | ||
56 | strcpy( lpTokenString, lpNewTokenString ); | ||
57 | |||
58 | // Now we do a preliminary parse. This could be effected by later | ||
59 | // editing and aliasing, but we'll see... | ||
60 | int nTkStart, nTkEnd; | ||
61 | int mode=0; // 0 = startSearch, 1=endSearch | ||
62 | for( int j = 0; j <= nLen; j++ ) | ||
63 | { | ||
64 | if( mode == 0 ) | ||
65 | { | ||
66 | if( lpTokenString[j] != ' ' && | ||
67 | lpTokenString[j] != '\t' ) | ||
68 | { | ||
69 | nTkStart = j; | ||
70 | mode = 1; | ||
71 | } | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | if( lpTokenString[j] == ' ' || | ||
76 | lpTokenString[j] == '\t' || | ||
77 | lpTokenString[j] == '\0' ) | ||
78 | { | ||
79 | nTkEnd = j-1; | ||
80 | mode = 0; | ||
81 | |||
82 | appendToken( nTkStart, nTkEnd ); | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | void TokenString::appendToken( int nStart, int nEnd ) | ||
89 | { | ||
90 | Token *pToken = new Token; | ||
91 | pToken->lpOrig = &lpTokenString[nStart]; | ||
92 | |||
93 | // nStart and nEnd are inclusive, we must add two for the end, and the null | ||
94 | pToken->lpToken = new char[nEnd-nStart+2]; | ||
95 | memcpy( pToken->lpToken, &lpTokenString[nStart], nEnd-nStart+1 ); | ||
96 | pToken->lpToken[nEnd-nStart+1] = '\0'; | ||
97 | |||
98 | // printf("%s\n", pToken->lpToken ); | ||
99 | lToken.append( pToken ); | ||
100 | } | ||
101 | |||
102 | void TokenString::insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ) | ||
103 | { | ||
104 | Token *pToken = new Token; | ||
105 | pToken->lpOrig = lpOldOrig; | ||
106 | |||
107 | // nStart and nEnd are inclusive, we must add two for the end, and the null | ||
108 | pToken->lpToken = new char[nEnd-nStart+2]; | ||
109 | memcpy( pToken->lpToken, &lpNewToken[nStart], nEnd-nStart+1 ); | ||
110 | pToken->lpToken[nEnd-nStart+1] = '\0'; | ||
111 | |||
112 | lToken.insertBefore( pToken, nIndex ); | ||
113 | } | ||
114 | |||
115 | int TokenString::getNumTokens() | ||
116 | { | ||
117 | return lToken.getSize(); | ||
118 | } | ||
119 | |||
120 | char *TokenString::getToken( int nIndex ) | ||
121 | { | ||
122 | if( nIndex >= lToken.getSize() ) return NULL; | ||
123 | return (char *)(((Token *)lToken[nIndex])->lpToken); | ||
124 | } | ||
125 | |||
126 | char *TokenString::getTokenString( int nIndex ) | ||
127 | { | ||
128 | if( nIndex >= lToken.getSize() ) return NULL; | ||
129 | return (char *)(((Token *)lToken[nIndex])->lpOrig); | ||
130 | } | ||
131 | |||
132 | void TokenString::expandTokenTo( int nIndex, char *lpNewToken ) | ||
133 | { | ||
134 | // First, we delete the token at nIndex, then we keep inserting | ||
135 | // at that position... | ||
136 | // We also have to remember the index to the original string, | ||
137 | // since most of what we're expanding to won't be in the origingal | ||
138 | // we need to keep these indexes updated in order to make other parts | ||
139 | // of the system happy. | ||
140 | char *lpOldOrig = ((Token *)lToken[nIndex])->lpOrig; | ||
141 | delete[] ((Token *)lToken[nIndex])->lpToken; | ||
142 | delete ((Token *)lToken[nIndex]); | ||
143 | lToken.deleteAt( nIndex ); | ||
144 | |||
145 | // We'll do this just like we did above, but instead we'll | ||
146 | // do tricky things when we find tokens... | ||
147 | int nLen = strlen(lpNewToken); | ||
148 | int nTkStart, nTkEnd, nNewIndex=nIndex; | ||
149 | int mode=0; // 0 = startSearch, 1=endSearch | ||
150 | for( int j = 0; j <= nLen; j++ ) | ||
151 | { | ||
152 | if( mode == 0 ) | ||
153 | { | ||
154 | if( lpNewToken[j] != ' ' && lpNewToken[j] != '\t' ) | ||
155 | { | ||
156 | nTkStart = j; | ||
157 | mode = 1; | ||
158 | } | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | if( lpNewToken[j] == ' ' || lpNewToken[j] == '\t' || lpNewToken[j] == '\0' ) | ||
163 | { | ||
164 | nTkEnd = j-1; | ||
165 | mode = 0; | ||
166 | |||
167 | insertToken( nTkStart, nTkEnd, lpOldOrig, lpNewToken, nNewIndex ); | ||
168 | nNewIndex++; | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | } | ||
diff --git a/src/tokenstring.h b/src/tokenstring.h new file mode 100644 index 0000000..25f710b --- /dev/null +++ b/src/tokenstring.h | |||
@@ -0,0 +1,120 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2003 by Mike Buland * | ||
3 | * eichlan@Xagafinelle * | ||
4 | * * | ||
5 | * This program is free software; you can redistribute it and/or modify * | ||
6 | * it under the terms of the GNU General Public License as published by * | ||
7 | * the Free Software Foundation; either version 2 of the License, or * | ||
8 | * (at your option) any later version. * | ||
9 | ***************************************************************************/ | ||
10 | #ifndef TOKENSTRING_H | ||
11 | #define TOKENSTRING_H | ||
12 | |||
13 | #include "linkedlist.h" | ||
14 | |||
15 | /** A single tokenized command line. Contains all information necesarry to | ||
16 | * nicely access a stand-alone command line and to perform alias expansion | ||
17 | * inside of that command line. | ||
18 | * When expanding a token, the original command line is left intact, so any | ||
19 | * command usng a command line verbatum (getTokenString not getToken) will get | ||
20 | * the original, and not the expanded version. | ||
21 | * Since indexing into the original command line is also done by token, it | ||
22 | * means that using getTokenString( 0 ) will not always get you the first | ||
23 | * character of the command line, it will get you the first non-whitespace | ||
24 | * character. | ||
25 | * Furthermore, when expanding the expantion string is tokenized as well, | ||
26 | * but since the original string is unchanged, all tokens that expand any | ||
27 | * given index will all retain the same index into the original command line. | ||
28 | *@todo Update this to allow it to break on different types of token | ||
29 | * delimiters. | ||
30 | *@author Mike Buland | ||
31 | */ | ||
32 | class TokenString{ | ||
33 | public: | ||
34 | /** Automatically call parseLine when created. | ||
35 | *@param lpNewTokenString The command line to tokenize | ||
36 | *@author Mike Buland | ||
37 | */ | ||
38 | TokenString( const char *lpNewTokenString=NULL ); | ||
39 | ~TokenString(); | ||
40 | |||
41 | /** Performs a tokenizing parse on the given command line, setting it as | ||
42 | * the internal command line for all future tokenizing (excluding | ||
43 | * expansion) | ||
44 | *@param lpNewTokenString The new command line to set to this object. | ||
45 | *@author Mike Buland | ||
46 | */ | ||
47 | void parseLine( const char *lpNewTokenString ); | ||
48 | |||
49 | /** Appends a token to the list of available tokens. This references the | ||
50 | * internal pointer to the command line, so no token string must be | ||
51 | * specified. | ||
52 | *@param nStart The first character of the token to insert. | ||
53 | *@param nEnd The last character of the token to insert. | ||
54 | *@author Mike Buland | ||
55 | */ | ||
56 | void appendToken( int nStart, int nEnd ); | ||
57 | |||
58 | /** Gets the number of tokens. This is particularly useful post-aliasing | ||
59 | * since the number of tokens may not match what is percieved from the | ||
60 | * original command line. | ||
61 | *@returns The number of available tokens. | ||
62 | *@author Mike Buland | ||
63 | */ | ||
64 | int getNumTokens(); | ||
65 | |||
66 | /** Gets a processed token specified by index. | ||
67 | *@param nIndex The index of the token to retrieve. | ||
68 | *@returns A pointer to the requested token. Please note that these tokens | ||
69 | * may not match the original command line. | ||
70 | *@author Mike Buland | ||
71 | */ | ||
72 | char *getToken( int nIndex ); | ||
73 | |||
74 | /** Gets the original command line based on tokens. Use this if you want | ||
75 | * to perform your own processing on parts of the command line, without | ||
76 | * resorting to tokens. | ||
77 | * The first character in the returned string will always be | ||
78 | * non-whitespace. | ||
79 | *@param nIndex The index of the token to start at, zero gets you the whole | ||
80 | * command line. | ||
81 | *@returns A pointer to the internal original command line string, starting | ||
82 | * at the position of the first non-whitespace character of the token | ||
83 | * specified. | ||
84 | *@author Mike Buland | ||
85 | */ | ||
86 | char *getTokenString( int nIndex=0 ); | ||
87 | |||
88 | /** Expands a token, replacing it with the string lpNewToken, but | ||
89 | * processing the new string for tokens before performing the replacement | ||
90 | *@param nIndex Which token should be replaced. | ||
91 | *@param lpNewToken The string to replace the token with. | ||
92 | *@author Mike Buland | ||
93 | */ | ||
94 | void expandTokenTo( int nIndex, char *lpNewToken ); | ||
95 | |||
96 | /** Inserts a token at any position in the command line. This does not | ||
97 | * effect the original command line. | ||
98 | *@param nStart The start of the token in the string lpNewToken. (inclusive) | ||
99 | *@param nEnd The end of the token in the string lpToken. (inclusive) | ||
100 | *@param lpOldOrig The pointer to the position in the orginal command | ||
101 | * line where this new token should point. | ||
102 | *@param lpNewToken The string containing the new token. May contain more | ||
103 | * than just one token. | ||
104 | *@param nIndex The position to insert the token to. | ||
105 | *@author Mike Buland | ||
106 | */ | ||
107 | void insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ); | ||
108 | |||
109 | private: | ||
110 | char *lpTokenString; | ||
111 | LinkedList lToken; | ||
112 | |||
113 | typedef struct Token | ||
114 | { | ||
115 | char *lpOrig; // This is just a pointer back to lpTokenString | ||
116 | char *lpToken; // This is really a whole token | ||
117 | } Token; | ||
118 | }; | ||
119 | |||
120 | #endif | ||
diff --git a/src/xmldocument.cpp b/src/xmldocument.cpp new file mode 100644 index 0000000..234ff81 --- /dev/null +++ b/src/xmldocument.cpp | |||
@@ -0,0 +1,142 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlwriter.h" | ||
4 | |||
5 | XmlDocument::XmlDocument( XmlNode *pRoot ) | ||
6 | { | ||
7 | this->pRoot = pRoot; | ||
8 | pCurrent = NULL; | ||
9 | bCompleted = (pRoot!=NULL); | ||
10 | } | ||
11 | |||
12 | XmlDocument::~XmlDocument() | ||
13 | { | ||
14 | if( pRoot ) | ||
15 | { | ||
16 | delete pRoot; | ||
17 | } | ||
18 | } | ||
19 | |||
20 | void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) | ||
21 | { | ||
22 | if( pRoot == NULL ) | ||
23 | { | ||
24 | // This is the first node, so ignore position and just insert it. | ||
25 | pCurrent = pRoot = new XmlNode( sName, NULL, sContent ); | ||
26 | } | ||
27 | else | ||
28 | { | ||
29 | pCurrent = pCurrent->addChild( sName, sContent ); | ||
30 | } | ||
31 | |||
32 | if( bClose ) | ||
33 | { | ||
34 | closeNode(); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | void XmlDocument::setName( const char *sName ) | ||
39 | { | ||
40 | pCurrent->setName( sName ); | ||
41 | } | ||
42 | |||
43 | bool XmlDocument::isCompleted() | ||
44 | { | ||
45 | return bCompleted; | ||
46 | } | ||
47 | |||
48 | XmlNode *XmlDocument::getRoot() | ||
49 | { | ||
50 | return pRoot; | ||
51 | } | ||
52 | |||
53 | XmlNode *XmlDocument::getCurrent() | ||
54 | { | ||
55 | return pCurrent; | ||
56 | } | ||
57 | |||
58 | void XmlDocument::closeNode() | ||
59 | { | ||
60 | if( pCurrent != NULL ) | ||
61 | { | ||
62 | pCurrent = pCurrent->getParent(); | ||
63 | |||
64 | if( pCurrent == NULL ) | ||
65 | { | ||
66 | bCompleted = true; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | void XmlDocument::addProperty( const char *sName, const char *sValue ) | ||
72 | { | ||
73 | if( pCurrent ) | ||
74 | { | ||
75 | pCurrent->addProperty( sName, sValue ); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | void XmlDocument::addProperty( const char *sName, const unsigned char nValue ) | ||
80 | { | ||
81 | char buf[12]; | ||
82 | sprintf( buf, "%hhi", nValue ); | ||
83 | addProperty( sName, buf ); | ||
84 | } | ||
85 | |||
86 | void XmlDocument::addProperty( const char *sName, const char nValue ) | ||
87 | { | ||
88 | char buf[12]; | ||
89 | sprintf( buf, "%hhi", nValue ); | ||
90 | addProperty( sName, buf ); | ||
91 | } | ||
92 | |||
93 | void XmlDocument::addProperty( const char *sName, const unsigned short nValue ) | ||
94 | { | ||
95 | char buf[12]; | ||
96 | sprintf( buf, "%hi", nValue ); | ||
97 | addProperty( sName, buf ); | ||
98 | } | ||
99 | |||
100 | void XmlDocument::addProperty( const char *sName, const short nValue ) | ||
101 | { | ||
102 | char buf[12]; | ||
103 | sprintf( buf, "%hi", nValue ); | ||
104 | addProperty( sName, buf ); | ||
105 | } | ||
106 | |||
107 | void XmlDocument::addProperty( const char *sName, const int nValue ) | ||
108 | { | ||
109 | char buf[12]; | ||
110 | sprintf( buf, "%li", nValue ); | ||
111 | addProperty( sName, buf ); | ||
112 | } | ||
113 | |||
114 | void XmlDocument::addProperty( const char *sName, const unsigned long nValue ) | ||
115 | { | ||
116 | char buf[12]; | ||
117 | sprintf( buf, "%li", nValue ); | ||
118 | addProperty( sName, buf ); | ||
119 | } | ||
120 | |||
121 | void XmlDocument::addProperty( const char *sName, const long nValue ) | ||
122 | { | ||
123 | char buf[12]; | ||
124 | sprintf( buf, "%li", nValue ); | ||
125 | addProperty( sName, buf ); | ||
126 | } | ||
127 | |||
128 | void XmlDocument::addProperty( const char *sName, const double dValue ) | ||
129 | { | ||
130 | char buf[40]; | ||
131 | sprintf( buf, "%f", dValue ); | ||
132 | addProperty( sName, buf ); | ||
133 | } | ||
134 | |||
135 | void XmlDocument::setContent( const char *sContent ) | ||
136 | { | ||
137 | if( pCurrent ) | ||
138 | { | ||
139 | pCurrent->setContent( sContent ); | ||
140 | } | ||
141 | } | ||
142 | |||
diff --git a/src/xmldocument.h b/src/xmldocument.h new file mode 100644 index 0000000..f9a8606 --- /dev/null +++ b/src/xmldocument.h | |||
@@ -0,0 +1,163 @@ | |||
1 | #ifndef XMLDOCUMENT | ||
2 | #define XMLDOCUMENT | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | |||
6 | /** | ||
7 | * Keeps track of an easily managed set of XmlNode information. Allows simple | ||
8 | * operations for logical writing to and reading from XML structures. Using | ||
9 | * already formed structures is simply done through the XmlNode structures, | ||
10 | * and the getRoot function here. Creation is performed through a simple set | ||
11 | * of operations that creates the data in a stream type format. | ||
12 | *@author Mike Buland | ||
13 | */ | ||
14 | class XmlDocument | ||
15 | { | ||
16 | public: | ||
17 | /** | ||
18 | * Construct either a blank XmlDocuemnt or construct a document around an | ||
19 | * existing XmlNode. Be careful, once an XmlNode is passed into a document | ||
20 | * the document takes over ownership and will delete it when the XmlDocument | ||
21 | * is deleted. | ||
22 | *@param pRoot The XmlNode to use as the root of this document, or NULL if | ||
23 | * you want to start a new document. | ||
24 | */ | ||
25 | XmlDocument( XmlNode *pRoot=NULL ); | ||
26 | |||
27 | /** | ||
28 | * Destroy all contained nodes. | ||
29 | */ | ||
30 | ~XmlDocument(); | ||
31 | |||
32 | /** | ||
33 | * Add a new node to the document. The new node is appended to the end of | ||
34 | * the current context, i.e. XmlNode, and the new node, provided it isn't | ||
35 | * close as part of this operation, will become the current context. | ||
36 | *@param sName The name of the new node to add. | ||
37 | *@param sContent A content string to be placed inside of the new node. | ||
38 | *@param bClose Set this to true to close the node immediately after adding | ||
39 | * the node and setting the content and name. If this is set to true the | ||
40 | * node is appended, but the context node doesn't change. | ||
41 | */ | ||
42 | void addNode( const char *sName=NULL, const char *sContent=NULL, bool bClose=false ); | ||
43 | |||
44 | /** | ||
45 | * Set the name of the current node context. | ||
46 | *@param sName The new name of the node. | ||
47 | */ | ||
48 | void setName( const char *sName ); | ||
49 | |||
50 | /** | ||
51 | * Close the current node context. This will move the current context to | ||
52 | * the parent node of the former current node. If the current node was the | ||
53 | * root then the "completed" flag is set and no more operations are allowed. | ||
54 | */ | ||
55 | void closeNode(); | ||
56 | |||
57 | /** | ||
58 | * Change the content of the current node at the current position between | ||
59 | * nodes. | ||
60 | *@param sContent The new content of the current node. | ||
61 | */ | ||
62 | void setContent( const char *sContent ); | ||
63 | |||
64 | /** | ||
65 | * Add a named property to the current context node. | ||
66 | *@param sName The name of the property to add. | ||
67 | *@param sValue The string value of the property. | ||
68 | */ | ||
69 | void addProperty( const char *sName, const char *sValue ); | ||
70 | |||
71 | /** | ||
72 | * Add a named property to the current context node, converting the | ||
73 | * numerical parameter to text using standrd printf style conversion. | ||
74 | *@param sName The name of the property to add. | ||
75 | *@param nValue The numerical value to add. | ||
76 | */ | ||
77 | void addProperty( const char *sName, const unsigned char nValue ); | ||
78 | |||
79 | /** | ||
80 | * Add a named property to the current context node, converting the | ||
81 | * numerical parameter to text using standrd printf style conversion. | ||
82 | *@param sName The name of the property to add. | ||
83 | *@param nValue The numerical value to add. | ||
84 | */ | ||
85 | void addProperty( const char *sName, const char nValue ); | ||
86 | |||
87 | /** | ||
88 | * Add a named property to the current context node, converting the | ||
89 | * numerical parameter to text using standrd printf style conversion. | ||
90 | *@param sName The name of the property to add. | ||
91 | *@param nValue The numerical value to add. | ||
92 | */ | ||
93 | void addProperty( const char *sName, const unsigned short nValue ); | ||
94 | |||
95 | /** | ||
96 | * Add a named property to the current context node, converting the | ||
97 | * numerical parameter to text using standrd printf style conversion. | ||
98 | *@param sName The name of the property to add. | ||
99 | *@param nValue The numerical value to add. | ||
100 | */ | ||
101 | void addProperty( const char *sName, const short nValue ); | ||
102 | |||
103 | /** | ||
104 | * Add a named property to the current context node, converting the | ||
105 | * numerical parameter to text using standrd printf style conversion. | ||
106 | *@param sName The name of the property to add. | ||
107 | *@param nValue The numerical value to add. | ||
108 | */ | ||
109 | void addProperty( const char *sName, const unsigned long nValue ); | ||
110 | |||
111 | /** | ||
112 | * Add a named property to the current context node, converting the | ||
113 | * numerical parameter to text using standrd printf style conversion. | ||
114 | *@param sName The name of the property to add. | ||
115 | *@param nValue The numerical value to add. | ||
116 | */ | ||
117 | void addProperty( const char *sName, const long nValue ); | ||
118 | |||
119 | /** | ||
120 | * Add a named property to the current context node, converting the | ||
121 | * numerical parameter to text using standrd printf style conversion. | ||
122 | *@param sName The name of the property to add. | ||
123 | *@param nValue The numerical value to add. | ||
124 | */ | ||
125 | void addProperty( const char *sName, const int nValue ); | ||
126 | |||
127 | /** | ||
128 | * Add a named property to the current context node, converting the | ||
129 | * numerical parameter to text using standrd printf style conversion. | ||
130 | *@param sName The name of the property to add. | ||
131 | *@param dValue The numerical value to add. | ||
132 | */ | ||
133 | void addProperty( const char *sName, const double dValue ); | ||
134 | |||
135 | /** | ||
136 | * The XmlDocuemnt is considered completed if the root node has been closed. | ||
137 | * Once an XmlDocument has been completed, you can no longer perform | ||
138 | * operations on it. | ||
139 | *@return True if completed, false if still in progress. | ||
140 | */ | ||
141 | bool isCompleted(); | ||
142 | |||
143 | /** | ||
144 | * Get a pointer to the root object of this XmlDocument. | ||
145 | *@returns A pointer to an internally owned XmlNode. Do not delete this | ||
146 | * XmlNode. | ||
147 | */ | ||
148 | XmlNode *getRoot(); | ||
149 | |||
150 | /** | ||
151 | * Get the current context node, which could be the same as the root node. | ||
152 | *@returns A pointer to an internally owned XmlNode. Do not delete this | ||
153 | * XmlNode. | ||
154 | */ | ||
155 | XmlNode *getCurrent(); | ||
156 | |||
157 | private: | ||
158 | XmlNode *pRoot; /**< The root node. */ | ||
159 | XmlNode *pCurrent; /**< The current node. */ | ||
160 | bool bCompleted; /**< Is it completed? */ | ||
161 | }; | ||
162 | |||
163 | #endif | ||
diff --git a/src/xmlfilereader.cpp b/src/xmlfilereader.cpp new file mode 100644 index 0000000..216c08a --- /dev/null +++ b/src/xmlfilereader.cpp | |||
@@ -0,0 +1,63 @@ | |||
1 | #include "xmlfilereader.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) | ||
5 | : XmlReader( bStrip ) | ||
6 | { | ||
7 | fh = fopen( sFile, "rt" ); | ||
8 | |||
9 | if( fh == NULL ) | ||
10 | { | ||
11 | reportError("Couldn't open file."); | ||
12 | //nError = 1; | ||
13 | } | ||
14 | else | ||
15 | { | ||
16 | char buf[50]; | ||
17 | fgets( buf, 50, fh ); | ||
18 | |||
19 | if( !strcmp( buf, "<?xml version=\"1.0\"?>\n" ) ) | ||
20 | { | ||
21 | buildDoc(); | ||
22 | } | ||
23 | } | ||
24 | } | ||
25 | |||
26 | XmlFileReader::~XmlFileReader() | ||
27 | { | ||
28 | } | ||
29 | |||
30 | char XmlFileReader::getChar( int nIndex ) | ||
31 | { | ||
32 | // Make sure we always have a little data left in the buffer | ||
33 | if( fbDataIn.getLength() <= nIndex+1 && fh ) | ||
34 | { | ||
35 | int nBytes = fbDataIn.getCapacity()-1; | ||
36 | char *buf = new char[nBytes]; | ||
37 | int nRead = fread( buf, 1, nBytes, fh ); | ||
38 | fbDataIn.appendData( buf, nRead ); | ||
39 | delete[] buf; | ||
40 | |||
41 | if( nRead < nBytes ) | ||
42 | { | ||
43 | fclose( fh ); | ||
44 | fh = NULL; | ||
45 | } | ||
46 | } | ||
47 | if( fbDataIn.getLength() >= nIndex+1 ) | ||
48 | { | ||
49 | return fbDataIn.getData()[nIndex]; | ||
50 | } | ||
51 | else | ||
52 | { | ||
53 | return '\0'; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | void XmlFileReader::usedChar() | ||
58 | { | ||
59 | if( fbDataIn.getLength() > 0 ) | ||
60 | { | ||
61 | fbDataIn.usedData( 1 ); | ||
62 | } | ||
63 | } | ||
diff --git a/src/xmlfilereader.h b/src/xmlfilereader.h new file mode 100644 index 0000000..3e996e6 --- /dev/null +++ b/src/xmlfilereader.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef XMLFILEREADER | ||
2 | #define XMLFILEREADER | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "xmlreader.h" | ||
6 | #include "flexbuf.h" | ||
7 | |||
8 | /** | ||
9 | * Takes care of reading in xml formatted data from a file. This could/should | ||
10 | * be made more arbitrary in the future so that we can read the data from any | ||
11 | * source. This is actually made quite simple already since all data read in | ||
12 | * is handled by one single helper function and then palced into a FlexBuf for | ||
13 | * easy access by the other functions. The FlexBuf also allows for block | ||
14 | * reading from disk, which improves speed by a noticable amount. | ||
15 | * <br> | ||
16 | * There are also some extra features implemented that allow you to break the | ||
17 | * standard XML reader specs and eliminate leading and trailing whitespace in | ||
18 | * all read content. This is useful in situations where you allow additional | ||
19 | * whitespace in the files to make them easily human readable. The resturned | ||
20 | * content will be NULL in sitautions where all content between nodes was | ||
21 | * stripped. | ||
22 | *@author Mike Buland | ||
23 | */ | ||
24 | class XmlFileReader : public XmlReader | ||
25 | { | ||
26 | public: | ||
27 | /** | ||
28 | * Construct an XmlReader around an xml file on your file system. | ||
29 | *@param sFile The file to read. | ||
30 | *@param bStrip Set to true to strip out leading and trailing whitespace in | ||
31 | * node contents. | ||
32 | */ | ||
33 | XmlFileReader( const char *sFile, bool bStrip=false ); | ||
34 | |||
35 | /** | ||
36 | * Destroy the reader and cleanup. | ||
37 | */ | ||
38 | ~XmlFileReader(); | ||
39 | |||
40 | private: | ||
41 | char getChar( int nIndex = 0 ); | ||
42 | void usedChar(); | ||
43 | FILE *fh; /**< The file handle. */ | ||
44 | FlexBuf fbDataIn; /**< The input buffer. */ | ||
45 | }; | ||
46 | |||
47 | #endif | ||
diff --git a/src/xmlfilewriter.cpp b/src/xmlfilewriter.cpp new file mode 100644 index 0000000..b62fb11 --- /dev/null +++ b/src/xmlfilewriter.cpp | |||
@@ -0,0 +1,22 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlfilewriter.h" | ||
4 | |||
5 | XmlFileWriter::XmlFileWriter( const char *sFileName, const char *sIndent, XmlNode *pRoot ) : | ||
6 | XmlWriter( sIndent, pRoot ) | ||
7 | { | ||
8 | this->sFileName = sFileName; | ||
9 | fh = fopen( sFileName, "wt"); | ||
10 | fprintf( fh, "<?xml version=\"1.0\"?>\n"); | ||
11 | } | ||
12 | |||
13 | XmlFileWriter::~XmlFileWriter() | ||
14 | { | ||
15 | fclose( fh ); | ||
16 | } | ||
17 | |||
18 | void XmlFileWriter::writeString( const char *sString ) | ||
19 | { | ||
20 | fprintf( fh, sString ); | ||
21 | } | ||
22 | |||
diff --git a/src/xmlfilewriter.h b/src/xmlfilewriter.h new file mode 100644 index 0000000..97b3e00 --- /dev/null +++ b/src/xmlfilewriter.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef XML_FILE_WRITER | ||
2 | #define XML_FILE_WRITER | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | #include "xmlwriter.h" | ||
6 | |||
7 | /** | ||
8 | * Implements xml writing in the XML standard format. Also allows you to | ||
9 | * break that format and auto-indent your exported xml data for ease of | ||
10 | * reading. The auto-indenting will only be applied to sections that | ||
11 | * have no content of their own already. This means that except for | ||
12 | * whitespace all of your data will be preserved perfectly. | ||
13 | * You can create an XmlWriter object around a file, or access the static | ||
14 | * write function directly and just hand it a filename and a root XmlNode. | ||
15 | * When using an XmlWriter object the interface is identicle to that of | ||
16 | * the XmlDocument class, so reference that class for API info. However | ||
17 | * when the initial (or root) node is closed, and the document is finished | ||
18 | * the file will be created and written to automatically. The user can | ||
19 | * check to see if this is actually true by calling the isFinished | ||
20 | * function in the XmlDocument class. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class XmlFileWriter : public XmlWriter | ||
24 | { | ||
25 | public: | ||
26 | /** | ||
27 | * Construct a file writer around a given file. | ||
28 | *@param sFileName The file to create or overwrite and write XML into. | ||
29 | *@param sIndent The indent text to use, if any. | ||
30 | */ | ||
31 | XmlFileWriter( const char *sFileName, const char *sIndent=NULL, XmlNode *pRoot=NULL ); | ||
32 | |||
33 | /** | ||
34 | * Destroy the writer. | ||
35 | */ | ||
36 | ~XmlFileWriter(); | ||
37 | |||
38 | private: | ||
39 | void writeString( const char *sString ); | ||
40 | std::string sFileName; /**< The filename to write to. */ | ||
41 | FILE *fh; /**< The file handle to the open file. */ | ||
42 | }; | ||
43 | |||
44 | #endif | ||
diff --git a/src/xmlnode.cpp b/src/xmlnode.cpp new file mode 100644 index 0000000..e5c77e2 --- /dev/null +++ b/src/xmlnode.cpp | |||
@@ -0,0 +1,454 @@ | |||
1 | #include "xmlnode.h" | ||
2 | #include "hashfunctionstring.h" | ||
3 | |||
4 | XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : | ||
5 | hProperties( new HashFunctionString(), 53, false ), | ||
6 | hChildren( new HashFunctionString(), 53, true ) | ||
7 | { | ||
8 | this->pParent = pParent; | ||
9 | if( sName != NULL ) | ||
10 | { | ||
11 | setName( sName ); | ||
12 | } | ||
13 | if( sContent != NULL ) | ||
14 | { | ||
15 | this->sPreContent = new std::string( sContent ); | ||
16 | } | ||
17 | else | ||
18 | { | ||
19 | this->sPreContent = NULL; | ||
20 | } | ||
21 | nCurContent = 0; | ||
22 | } | ||
23 | |||
24 | XmlNode::~XmlNode() | ||
25 | { | ||
26 | for( int j = 0; j < lChildren.getSize(); j++ ) | ||
27 | { | ||
28 | delete (XmlNode *)lChildren[j]; | ||
29 | } | ||
30 | for( int j = 0; j < lPropNames.getSize(); j++ ) | ||
31 | { | ||
32 | delete (std::string *)lPropNames[j]; | ||
33 | } | ||
34 | for( int j = 0; j < lPropValues.getSize(); j++ ) | ||
35 | { | ||
36 | delete (std::string *)lPropValues[j]; | ||
37 | } | ||
38 | for( int j = 0; j < lPostContent.getSize(); j++ ) | ||
39 | { | ||
40 | if( lPostContent[j] != NULL ) | ||
41 | { | ||
42 | delete (std::string *)lPostContent[j]; | ||
43 | } | ||
44 | } | ||
45 | if( sPreContent ) | ||
46 | { | ||
47 | delete sPreContent; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | void XmlNode::setName( const char *sName ) | ||
52 | { | ||
53 | if( pParent ) | ||
54 | { | ||
55 | if( this->sName.size() == 0 ) | ||
56 | { | ||
57 | // We're not in the hash yet, so add us | ||
58 | this->sName = sName; | ||
59 | pParent->hChildren.insert( this->sName.c_str(), this ); | ||
60 | } | ||
61 | else | ||
62 | { | ||
63 | // Slightly more tricky, delete us, then add us... | ||
64 | pParent->hChildren.del( this->sName.c_str() ); | ||
65 | this->sName = sName; | ||
66 | pParent->hChildren.insert( this->sName.c_str(), this ); | ||
67 | } | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | // If we have no parent, then just set the name string, we don't need | ||
72 | // to worry about hashing. | ||
73 | this->sName = sName; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void XmlNode::setContent( const char *sContent, int nIndex ) | ||
78 | { | ||
79 | if( nIndex == -1 ) | ||
80 | { | ||
81 | nIndex = nCurContent; | ||
82 | } | ||
83 | if( nIndex == 0 ) | ||
84 | { | ||
85 | if( this->sPreContent ) | ||
86 | { | ||
87 | delete this->sPreContent; | ||
88 | } | ||
89 | |||
90 | this->sPreContent = new std::string( sContent ); | ||
91 | } | ||
92 | else | ||
93 | { | ||
94 | nIndex--; | ||
95 | if( lPostContent[nIndex] ) | ||
96 | { | ||
97 | delete (std::string *)lPostContent[nIndex]; | ||
98 | } | ||
99 | |||
100 | lPostContent.setAt( nIndex, new std::string( sContent ) ); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | const char *XmlNode::getContent( int nIndex ) | ||
105 | { | ||
106 | if( nIndex == 0 ) | ||
107 | { | ||
108 | if( sPreContent ) | ||
109 | { | ||
110 | return sPreContent->c_str(); | ||
111 | } | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | nIndex--; | ||
116 | if( lPostContent[nIndex] ) | ||
117 | { | ||
118 | return ((std::string *)lPostContent[nIndex])->c_str(); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) | ||
126 | { | ||
127 | return addChild( new XmlNode( sName, this, sContent ) ); | ||
128 | } | ||
129 | |||
130 | XmlNode *XmlNode::addChild( XmlNode *pNode ) | ||
131 | { | ||
132 | lChildren.append( pNode ); | ||
133 | lPostContent.append( NULL ); | ||
134 | nCurContent++; | ||
135 | pNode->pParent = this; | ||
136 | |||
137 | return pNode; | ||
138 | } | ||
139 | |||
140 | XmlNode *XmlNode::getParent() | ||
141 | { | ||
142 | return pParent; | ||
143 | } | ||
144 | |||
145 | void XmlNode::addProperty( const char *sName, const char *sValue ) | ||
146 | { | ||
147 | std::string *pName = new std::string( sName ); | ||
148 | std::string *pValue = new std::string( sValue ); | ||
149 | |||
150 | hProperties.insert( pName->c_str(), pValue->c_str() ); | ||
151 | lPropNames.append( pName ); | ||
152 | lPropValues.append( pValue ); | ||
153 | } | ||
154 | |||
155 | int XmlNode::getNumProperties() | ||
156 | { | ||
157 | return lPropNames.getSize(); | ||
158 | } | ||
159 | |||
160 | const char *XmlNode::getPropertyName( int nIndex ) | ||
161 | { | ||
162 | std::string *tmp = ((std::string *)lPropNames[nIndex]); | ||
163 | if( tmp == NULL ) | ||
164 | return NULL; | ||
165 | return tmp->c_str(); | ||
166 | } | ||
167 | |||
168 | const char *XmlNode::getProperty( int nIndex ) | ||
169 | { | ||
170 | std::string *tmp = ((std::string *)lPropValues[nIndex]); | ||
171 | if( tmp == NULL ) | ||
172 | return NULL; | ||
173 | return tmp->c_str(); | ||
174 | } | ||
175 | |||
176 | const char *XmlNode::getProperty( const char *sName ) | ||
177 | { | ||
178 | const char *tmp = (const char *)hProperties[sName]; | ||
179 | if( tmp == NULL ) | ||
180 | return NULL; | ||
181 | return tmp; | ||
182 | } | ||
183 | |||
184 | bool XmlNode::deleteProperty( int nIndex ) | ||
185 | { | ||
186 | hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); | ||
187 | |||
188 | delete (std::string *)lPropNames[nIndex]; | ||
189 | delete (std::string *)lPropValues[nIndex]; | ||
190 | |||
191 | lPropNames.deleteAt( nIndex ); | ||
192 | lPropValues.deleteAt( nIndex ); | ||
193 | } | ||
194 | |||
195 | bool XmlNode::hasChildren() | ||
196 | { | ||
197 | return lChildren.getSize()>0; | ||
198 | } | ||
199 | |||
200 | int XmlNode::getNumChildren() | ||
201 | { | ||
202 | return lChildren.getSize(); | ||
203 | } | ||
204 | |||
205 | XmlNode *XmlNode::getChild( int nIndex ) | ||
206 | { | ||
207 | return (XmlNode *)lChildren[nIndex]; | ||
208 | } | ||
209 | |||
210 | XmlNode *XmlNode::getChild( const char *sName, int nSkip ) | ||
211 | { | ||
212 | return (XmlNode *)hChildren.get( sName, nSkip ); | ||
213 | } | ||
214 | |||
215 | const char *XmlNode::getName() | ||
216 | { | ||
217 | return sName.c_str(); | ||
218 | } | ||
219 | |||
220 | bool XmlNode::deleteNode( int nIndex, const char *sReplacementText ) | ||
221 | { | ||
222 | XmlNode *xRet = detatchNode( nIndex, sReplacementText ); | ||
223 | |||
224 | if( xRet == NULL ) | ||
225 | { | ||
226 | return false; | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | delete xRet; | ||
231 | return true; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | XmlNode *XmlNode::detatchNode( int nIndex, const char *sReplacementText ) | ||
236 | { | ||
237 | if( nIndex < 0 || nIndex >= lChildren.getSize() ) | ||
238 | return NULL; | ||
239 | |||
240 | // The real trick when deleteing a node isn't actually deleting it, it's | ||
241 | // reforming the content around the node that's now missing...hmmm... | ||
242 | |||
243 | if( nIndex == 0 ) | ||
244 | { | ||
245 | // If the index is zero we have to deal with the pre-content | ||
246 | if( sReplacementText ) | ||
247 | { | ||
248 | if( sPreContent == NULL ) | ||
249 | { | ||
250 | sPreContent = new std::string( sReplacementText ); | ||
251 | } | ||
252 | else | ||
253 | { | ||
254 | *sPreContent += sReplacementText; | ||
255 | } | ||
256 | } | ||
257 | if( lPostContent.getSize() > 0 ) | ||
258 | { | ||
259 | if( lPostContent[0] != NULL ) | ||
260 | { | ||
261 | if( sPreContent == NULL ) | ||
262 | { | ||
263 | sPreContent = new std::string( | ||
264 | ((std::string *)lPostContent[0])->c_str() | ||
265 | ); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | *sPreContent += | ||
270 | ((std::string *)lPostContent[0])->c_str(); | ||
271 | } | ||
272 | } | ||
273 | delete (std::string *)lPostContent[0]; | ||
274 | lPostContent.deleteAt( 0 ); | ||
275 | } | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | int nCont = nIndex-1; | ||
280 | // If it's above zero we deal with the post-content only | ||
281 | if( sReplacementText ) | ||
282 | { | ||
283 | if( lPostContent[nCont] == NULL ) | ||
284 | { | ||
285 | lPostContent.setAt( nCont, new std::string( sReplacementText ) ); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | *((std::string *)lPostContent[nCont]) += sReplacementText; | ||
290 | } | ||
291 | } | ||
292 | if( lPostContent.getSize() > nIndex ) | ||
293 | { | ||
294 | if( lPostContent[nIndex] != NULL ) | ||
295 | { | ||
296 | if( lPostContent[nCont] == NULL ) | ||
297 | { | ||
298 | lPostContent.setAt( nCont, new std::string( | ||
299 | ((std::string *)lPostContent[nIndex])->c_str() | ||
300 | ) ); | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | *((std::string *)lPostContent[nCont]) += | ||
305 | ((std::string *)lPostContent[nIndex])->c_str(); | ||
306 | } | ||
307 | } | ||
308 | delete (std::string *)lPostContent[nIndex]; | ||
309 | lPostContent.deleteAt( nIndex ); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | XmlNode *xRet = (XmlNode *)lChildren[nIndex]; | ||
314 | hChildren.del( ((XmlNode *)lChildren[nIndex])->getName() ); | ||
315 | lChildren.deleteAt( nIndex ); | ||
316 | |||
317 | return xRet; | ||
318 | } | ||
319 | |||
320 | bool XmlNode::replaceNode( int nIndex, XmlNode *pNewNode ) | ||
321 | { | ||
322 | if( nIndex < 0 || nIndex >= lChildren.getSize() ) | ||
323 | return false; | ||
324 | |||
325 | delete (XmlNode *)lChildren[nIndex]; | ||
326 | lChildren.setAt( nIndex, pNewNode ); | ||
327 | pNewNode->pParent = this; | ||
328 | |||
329 | return true; | ||
330 | } | ||
331 | |||
332 | XmlNode *XmlNode::getCopy() | ||
333 | { | ||
334 | XmlNode *pNew = new XmlNode(); | ||
335 | |||
336 | pNew->sName = sName; | ||
337 | if( sPreContent ) | ||
338 | { | ||
339 | pNew->sPreContent = new std::string( sPreContent->c_str() ); | ||
340 | } | ||
341 | else | ||
342 | { | ||
343 | pNew->sPreContent = NULL; | ||
344 | } | ||
345 | pNew->nCurContent = 0; | ||
346 | |||
347 | int nSize = lPostContent.getSize(); | ||
348 | pNew->lPostContent.setSize( nSize ); | ||
349 | for( int j = 0; j < nSize; j++ ) | ||
350 | { | ||
351 | if( lPostContent[j] ) | ||
352 | { | ||
353 | pNew->lPostContent.setAt( | ||
354 | j, new std::string( | ||
355 | ((std::string *)lPostContent[j])->c_str() | ||
356 | ) | ||
357 | ); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | pNew->lPostContent.setAt( j, NULL ); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | nSize = lChildren.getSize(); | ||
366 | pNew->lChildren.setSize( nSize ); | ||
367 | for( int j = 0; j < nSize; j++ ) | ||
368 | { | ||
369 | XmlNode *pChild = ((XmlNode *)lChildren[j])->getCopy(); | ||
370 | pNew->lChildren.setAt( j, pChild ); | ||
371 | pChild->pParent = this; | ||
372 | hChildren.insert( pChild->getName(), pChild ); | ||
373 | } | ||
374 | |||
375 | nSize = lPropNames.getSize(); | ||
376 | pNew->lPropNames.setSize( nSize ); | ||
377 | pNew->lPropValues.setSize( nSize ); | ||
378 | for( int j = 0; j < nSize; j++ ) | ||
379 | { | ||
380 | std::string *pProp = new std::string( ((std::string *)lPropNames[j])->c_str() ); | ||
381 | std::string *pVal = new std::string( ((std::string *)lPropValues[j])->c_str() ); | ||
382 | pNew->lPropNames.setAt( j, pProp ); | ||
383 | pNew->lPropValues.setAt( j, pVal ); | ||
384 | pNew->hProperties.insert( pProp->c_str(), pVal->c_str() ); | ||
385 | pNew->nCurContent++; | ||
386 | } | ||
387 | |||
388 | return pNew; | ||
389 | } | ||
390 | |||
391 | bool XmlNode::deleteNodeKeepChildren( int nIndex ) | ||
392 | { | ||
393 | // This is a tricky one...we need to do some patching to keep things all | ||
394 | // even... | ||
395 | XmlNode *xRet = (XmlNode *)lChildren[nIndex]; | ||
396 | |||
397 | if( xRet == NULL ) | ||
398 | { | ||
399 | return false; | ||
400 | } | ||
401 | else | ||
402 | { | ||
403 | if( getContent( nIndex ) ) | ||
404 | { | ||
405 | std::string sBuf( getContent( nIndex ) ); | ||
406 | sBuf += xRet->getContent( 0 ); | ||
407 | setContent( sBuf.c_str(), nIndex ); | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | setContent( xRet->getContent( 0 ), nIndex ); | ||
412 | } | ||
413 | |||
414 | int nSize = xRet->lChildren.getSize(); | ||
415 | for( int j = 0; j < nSize; j++ ) | ||
416 | { | ||
417 | XmlNode *pCopy = ((XmlNode *)xRet->lChildren[j])->getCopy(); | ||
418 | pCopy->pParent = this; | ||
419 | lChildren.insertBefore( pCopy, nIndex+j ); | ||
420 | |||
421 | if( xRet->lPostContent[j] ) | ||
422 | { | ||
423 | lPostContent.insertBefore( | ||
424 | new std::string( ((std::string *)xRet->lPostContent[j])->c_str() ), | ||
425 | nIndex+j | ||
426 | ); | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | lPostContent.insertBefore( NULL, nIndex+j ); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | if( getContent( nIndex+nSize ) ) | ||
435 | { | ||
436 | //SString sBuf( getContent( nIndex+nSize ) ); | ||
437 | //sBuf.catfrom( xRet->getContent( nSize ) ); | ||
438 | //setContent( sBuf, nIndex+nSize ); | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | setContent( xRet->getContent( nSize ), nIndex+nSize ); | ||
443 | } | ||
444 | |||
445 | deleteNode( nIndex+nSize ); | ||
446 | return true; | ||
447 | } | ||
448 | |||
449 | } | ||
450 | |||
451 | bool XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) | ||
452 | { | ||
453 | } | ||
454 | |||
diff --git a/src/xmlnode.h b/src/xmlnode.h new file mode 100644 index 0000000..2b01226 --- /dev/null +++ b/src/xmlnode.h | |||
@@ -0,0 +1,236 @@ | |||
1 | #ifndef XMLNODE | ||
2 | #define XMLNODE | ||
3 | |||
4 | #include <iostream> | ||
5 | #include "linkedlist.h" | ||
6 | #include "hashtable.h" | ||
7 | |||
8 | /** | ||
9 | * Maintains all data pertient to an XML node, including sub-nodes and content. | ||
10 | * All child nodes can be accessed through index and through name via a hash | ||
11 | * table. This makes it very easy to gain simple and fast access to all of | ||
12 | * your data. For most applications, the memory footprint is also rather | ||
13 | * small. While XmlNode objects can be used directly to create XML structures | ||
14 | * it is highly reccomended that all operations be performed through the | ||
15 | * XmlDocument class. | ||
16 | *@author Mike Buland | ||
17 | */ | ||
18 | class XmlNode | ||
19 | { | ||
20 | public: | ||
21 | /** | ||
22 | * Construct a new XmlNode. | ||
23 | *@param sName The name of the node. | ||
24 | *@param pParent The parent node. | ||
25 | *@param sContent The initial content string. | ||
26 | */ | ||
27 | XmlNode( | ||
28 | const char *sName=NULL, | ||
29 | XmlNode *pParent = NULL, | ||
30 | const char *sContent=NULL | ||
31 | ); | ||
32 | |||
33 | /** | ||
34 | * Delete the node and cleanup all memory. | ||
35 | */ | ||
36 | ~XmlNode(); | ||
37 | |||
38 | /** | ||
39 | * Change the name of the node. | ||
40 | *@param sName The new name of the node. | ||
41 | */ | ||
42 | void setName( const char *sName ); | ||
43 | |||
44 | /** | ||
45 | * Construct a new node and add it as a child to this node, also return a | ||
46 | * pointer to the newly constructed node. | ||
47 | *@param sName The name of the new node. | ||
48 | *@param sContent The initial content of the new node. | ||
49 | *@returns A pointer to the newly created child node. | ||
50 | */ | ||
51 | XmlNode *addChild( const char *sName, const char *sContent=NULL ); | ||
52 | |||
53 | /** | ||
54 | * Add an already created XmlNode as a child to this node. The new child | ||
55 | * XmlNode's parent will be changed appropriately and the parent XmlNode | ||
56 | * will take ownership of the child. | ||
57 | *@param pChild The child XmlNode to add to this XmlNode. | ||
58 | *@returns A pointer to the child node that was just added. | ||
59 | */ | ||
60 | XmlNode *addChild( XmlNode *pChild ); | ||
61 | |||
62 | /** | ||
63 | * Add a new property to the XmlNode. Properties are name/value pairs. | ||
64 | *@param sName The name of the property. Specifying a name that's already | ||
65 | * in use will overwrite that property. | ||
66 | *@param sValue The textual value of the property. | ||
67 | */ | ||
68 | void addProperty( const char *sName, const char *sValue ); | ||
69 | |||
70 | /** | ||
71 | * Get a pointer to the parent node, if any. | ||
72 | *@returns A pointer to the node's parent, or NULL if there isn't one. | ||
73 | */ | ||
74 | XmlNode *getParent(); | ||
75 | |||
76 | /** | ||
77 | * Tells you if this node has children. | ||
78 | *@returns True if this node has at least one child, false otherwise. | ||
79 | */ | ||
80 | bool hasChildren(); | ||
81 | |||
82 | /** | ||
83 | * Tells you how many children this node has. | ||
84 | *@returns The number of children this node has. | ||
85 | */ | ||
86 | int getNumChildren(); | ||
87 | |||
88 | /** | ||
89 | * Get a child node at a specific index. | ||
90 | *@param nIndex The zero-based index of the child to retreive. | ||
91 | *@returns A pointer to the child, or NULL if you requested an invalid | ||
92 | * index. | ||
93 | */ | ||
94 | XmlNode *getChild( int nIndex ); | ||
95 | |||
96 | /** | ||
97 | * Get a child with the specified name, and possibly skip value. For an | ||
98 | * explination of skip values see the HashTable. | ||
99 | *@param sName The name of the child to find. | ||
100 | *@param nSkip The number of nodes with that name to skip. | ||
101 | *@returns A pointer to the child, or NULL if no child with that name was | ||
102 | * found. | ||
103 | */ | ||
104 | XmlNode *getChild( const char *sName, int nSkip=0 ); | ||
105 | |||
106 | /** | ||
107 | * Get a pointer to the name of this node. Do not change this, use setName | ||
108 | * instead. | ||
109 | *@returns A pointer to the name of this node. | ||
110 | */ | ||
111 | const char *getName(); | ||
112 | |||
113 | /** | ||
114 | * Set the content of this node, optionally at a specific index. Using the | ||
115 | * default of -1 will set the content after the last added node. | ||
116 | *@param sContent The content string to use. | ||
117 | *@param nIndex The index of the content. | ||
118 | */ | ||
119 | void setContent( const char *sContent, int nIndex=-1 ); | ||
120 | |||
121 | /** | ||
122 | * Get the content string at a given index, or zero for initial content. | ||
123 | *@param nIndex The index of the content. | ||
124 | *@returns A pointer to the content at that location. | ||
125 | */ | ||
126 | const char *getContent( int nIndex = 0 ); | ||
127 | |||
128 | /** | ||
129 | * Get the number of properties in this node. | ||
130 | *@returns The number of properties in this node. | ||
131 | */ | ||
132 | int getNumProperties(); | ||
133 | |||
134 | /** | ||
135 | * Get a property's name by index. | ||
136 | *@param nIndex The index of the property to examine. | ||
137 | *@returns A pointer to the name of the property specified, or NULL if none | ||
138 | * found. | ||
139 | */ | ||
140 | const char *getPropertyName( int nIndex ); | ||
141 | |||
142 | /** | ||
143 | * Get a proprty's value by index. | ||
144 | *@param nIndex The index of the property to examine. | ||
145 | *@returns A pointer to the value of the property specified, or NULL if none | ||
146 | * found. | ||
147 | */ | ||
148 | const char *getProperty( int nIndex ); | ||
149 | |||
150 | /** | ||
151 | * Get a propery's value by name. | ||
152 | *@param sName The name of the property to examine. | ||
153 | *@returns A pointer to the value of the property specified, or NULL if none | ||
154 | * found. | ||
155 | */ | ||
156 | const char *getProperty( const char *sName ); | ||
157 | |||
158 | /** | ||
159 | * Delete a property by index. | ||
160 | *@param nIndex The index of the property to delete. | ||
161 | *@returns True if the property was found and deleted, false if it wasn't | ||
162 | * found. | ||
163 | */ | ||
164 | bool deleteProperty( int nIndex ); | ||
165 | |||
166 | /** | ||
167 | * Delete a child node, possibly replacing it with some text. This actually | ||
168 | * fixes all content strings around the newly deleted child node. | ||
169 | *@param nIndex The index of the node to delete. | ||
170 | *@param sReplacementText The optional text to replace the node with. | ||
171 | *@returns True of the node was found, and deleted, false if it wasn't | ||
172 | * found. | ||
173 | */ | ||
174 | bool deleteNode( int nIndex, const char *sReplacementText = NULL ); | ||
175 | |||
176 | /** | ||
177 | * Delete a given node, but move all of it's children and content up to | ||
178 | * replace the deleted node. All of the content of the child node is | ||
179 | * spliced seamlessly into place with the parent node's content. | ||
180 | *@param nIndex The node to delete. | ||
181 | *@returns True if the node was found and deleted, false if it wasn't. | ||
182 | */ | ||
183 | bool deleteNodeKeepChildren( int nIndex ); | ||
184 | |||
185 | /** | ||
186 | * Detatch a given child node from this node. This effectively works just | ||
187 | * like a deleteNode, except that instead of deleting the node it is removed | ||
188 | * and returned, and all ownership is given up. | ||
189 | *@param nIndex The index of the node to detatch. | ||
190 | *@param sReplacementText The optional text to replace the detatched node | ||
191 | * with. | ||
192 | *@returns A pointer to the newly detatched node, which then passes | ||
193 | * ownership to the caller. | ||
194 | */ | ||
195 | XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); | ||
196 | |||
197 | /** | ||
198 | * Replace a given node with a different node that is not currently owned by | ||
199 | * this XmlNode or any ancestor. | ||
200 | *@param nIndex The index of the node to replace. | ||
201 | *@param pNewNode The new node to replace the old node with. | ||
202 | *@returns True if the node was found and replaced, false if it wasn't. | ||
203 | */ | ||
204 | bool replaceNode( int nIndex, XmlNode *pNewNode ); | ||
205 | |||
206 | /** | ||
207 | * Replace a given node with the children and content of a given node. | ||
208 | *@param nIndex The index of the node to replace. | ||
209 | *@param pNewNode The node that contains the children and content that will | ||
210 | * replace the node specified by nIndex. | ||
211 | *@returns True if the node was found and replaced, false if it wasn't. | ||
212 | */ | ||
213 | bool replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); | ||
214 | |||
215 | /** | ||
216 | * Get a copy of this node and all children. getCopy is recursive, so | ||
217 | * beware copying large trees of xml. | ||
218 | *@returns A newly created copy of this node and all of it's children. | ||
219 | */ | ||
220 | XmlNode *getCopy(); | ||
221 | |||
222 | private: | ||
223 | std::string sName; /**< The name of the node. */ | ||
224 | std::string *sPreContent; /**< The content that goes before any node. */ | ||
225 | LinkedList lChildren; /**< The children. */ | ||
226 | LinkedList lPostContent; /**< The content that comes after children. */ | ||
227 | HashTable hProperties; /**< Property hashtable. */ | ||
228 | HashTable hChildren; /**< Children hashtable. */ | ||
229 | LinkedList lPropNames; /**< List of property names. */ | ||
230 | LinkedList lPropValues; /**< List of property values. */ | ||
231 | XmlNode *pParent; /**< A pointer to the parent of this node. */ | ||
232 | int nCurContent; /**< The current content we're on, for using the -1 on | ||
233 | setContent. */ | ||
234 | }; | ||
235 | |||
236 | #endif | ||
diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp new file mode 100644 index 0000000..bb24157 --- /dev/null +++ b/src/xmlreader.cpp | |||
@@ -0,0 +1,412 @@ | |||
1 | #include "xmlreader.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | XmlReader::XmlReader( bool bStrip ) | ||
5 | { | ||
6 | nError = 0; | ||
7 | this->bStrip = bStrip; | ||
8 | } | ||
9 | |||
10 | XmlReader::~XmlReader() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | #define gcall( x ) if( x == false ) return false; | ||
15 | |||
16 | bool XmlReader::isws( char chr ) | ||
17 | { | ||
18 | return ( chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' ); | ||
19 | } | ||
20 | |||
21 | bool XmlReader::ws() | ||
22 | { | ||
23 | while( true ) | ||
24 | { | ||
25 | char chr = getChar(); | ||
26 | if( isws( chr ) ) | ||
27 | { | ||
28 | usedChar(); | ||
29 | } | ||
30 | else | ||
31 | { | ||
32 | return true; | ||
33 | } | ||
34 | } | ||
35 | return true; | ||
36 | } | ||
37 | |||
38 | bool XmlReader::buildDoc() | ||
39 | { | ||
40 | // take care of initial whitespace | ||
41 | gcall( ws() ); | ||
42 | gcall( node() ); | ||
43 | |||
44 | return true; | ||
45 | } | ||
46 | |||
47 | bool XmlReader::node() | ||
48 | { | ||
49 | gcall( startNode() ) | ||
50 | |||
51 | // At this point, we are closing the startNode | ||
52 | char chr = getChar(); | ||
53 | if( chr == '>' ) | ||
54 | { | ||
55 | usedChar(); | ||
56 | |||
57 | // Now we process the guts of the node. | ||
58 | gcall( content() ); | ||
59 | } | ||
60 | else if( chr == '/' ) | ||
61 | { | ||
62 | // This is the tricky one, one more validation, then we close the node. | ||
63 | usedChar(); | ||
64 | if( getChar() == '>' ) | ||
65 | { | ||
66 | closeNode(); | ||
67 | usedChar(); | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | reportError("Close node in singleNode malformed!"); | ||
72 | return false; | ||
73 | } | ||
74 | } | ||
75 | else | ||
76 | { | ||
77 | reportError("Close node expected, but not found."); | ||
78 | return false; | ||
79 | } | ||
80 | |||
81 | return true; | ||
82 | } | ||
83 | |||
84 | bool XmlReader::startNode() | ||
85 | { | ||
86 | if( getChar() == '<' ) | ||
87 | { | ||
88 | usedChar(); | ||
89 | |||
90 | if( getChar() == '/' ) | ||
91 | { | ||
92 | // Heh, it's actually a close node, go figure | ||
93 | FlexBuf fbName; | ||
94 | usedChar(); | ||
95 | gcall( ws() ); | ||
96 | |||
97 | while( true ) | ||
98 | { | ||
99 | char chr = getChar(); | ||
100 | if( isws( chr ) || chr == '>' ) | ||
101 | { | ||
102 | // Here we actually compare the name we got to the name | ||
103 | // we already set, they have to match exactly. | ||
104 | if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) | ||
105 | { | ||
106 | closeNode(); | ||
107 | break; | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | reportError("Got a mismatched node close tag."); | ||
112 | return false; | ||
113 | } | ||
114 | } | ||
115 | else | ||
116 | { | ||
117 | fbName.appendData( chr ); | ||
118 | usedChar(); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | gcall( ws() ); | ||
123 | if( getChar() == '>' ) | ||
124 | { | ||
125 | // Everything is cool. | ||
126 | usedChar(); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | reportError("Got extra junk data instead of node close tag."); | ||
131 | return false; | ||
132 | } | ||
133 | } | ||
134 | else | ||
135 | { | ||
136 | // We're good, format is consistant | ||
137 | addNode(); | ||
138 | |||
139 | // Skip extra whitespace | ||
140 | gcall( ws() ); | ||
141 | gcall( name() ); | ||
142 | gcall( ws() ); | ||
143 | gcall( paramlist() ); | ||
144 | gcall( ws() ); | ||
145 | } | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | reportError("Expected to find node opening char, '<'.\n"); | ||
150 | return false; | ||
151 | } | ||
152 | |||
153 | return true; | ||
154 | } | ||
155 | |||
156 | bool XmlReader::name() | ||
157 | { | ||
158 | FlexBuf fbName; | ||
159 | |||
160 | while( true ) | ||
161 | { | ||
162 | char chr = getChar(); | ||
163 | if( isws( chr ) || chr == '>' || chr == '/' ) | ||
164 | { | ||
165 | setName( fbName.getData() ); | ||
166 | return true; | ||
167 | } | ||
168 | else | ||
169 | { | ||
170 | fbName.appendData( chr ); | ||
171 | usedChar(); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return true; | ||
176 | } | ||
177 | |||
178 | bool XmlReader::paramlist() | ||
179 | { | ||
180 | while( true ) | ||
181 | { | ||
182 | char chr = getChar(); | ||
183 | if( chr == '/' || chr == '>' ) | ||
184 | { | ||
185 | return true; | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | gcall( param() ); | ||
190 | gcall( ws() ); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | return true; | ||
195 | } | ||
196 | |||
197 | char XmlReader::getEscape() | ||
198 | { | ||
199 | // Right now, we just do # escapes... | ||
200 | if( getChar( 1 ) == '#' ) | ||
201 | { | ||
202 | usedChar(); | ||
203 | usedChar(); | ||
204 | char buf[4]; | ||
205 | int j = 0; | ||
206 | for( j = 0; getChar() != ';'; j++ ) | ||
207 | { | ||
208 | buf[j] = getChar(); | ||
209 | usedChar(); | ||
210 | } | ||
211 | usedChar(); | ||
212 | buf[j] = '\0'; | ||
213 | return (char)atoi( buf ); | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | return '\0'; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | bool XmlReader::param() | ||
222 | { | ||
223 | FlexBuf fbName; | ||
224 | FlexBuf fbValue; | ||
225 | |||
226 | while( true ) | ||
227 | { | ||
228 | char chr = getChar(); | ||
229 | if( isws( chr ) || chr == '=' ) | ||
230 | { | ||
231 | break; | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | fbName.appendData( chr ); | ||
236 | usedChar(); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | gcall( ws() ); | ||
241 | |||
242 | if( getChar() == '=' ) | ||
243 | { | ||
244 | usedChar(); | ||
245 | |||
246 | gcall( ws() ); | ||
247 | |||
248 | char chr = getChar(); | ||
249 | if( chr == '"' ) | ||
250 | { | ||
251 | // Better quoted rhs | ||
252 | usedChar(); | ||
253 | |||
254 | while( true ) | ||
255 | { | ||
256 | chr = getChar(); | ||
257 | if( chr == '"' ) | ||
258 | { | ||
259 | usedChar(); | ||
260 | addProperty( fbName.getData(), fbValue.getData() ); | ||
261 | return true; | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | if( chr == '&' ) | ||
266 | { | ||
267 | chr = getEscape(); | ||
268 | if( chr == '\0' ) return false; | ||
269 | fbValue.appendData( chr ); | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | fbValue.appendData( chr ); | ||
274 | usedChar(); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | else | ||
280 | { | ||
281 | // Simple one-word rhs | ||
282 | while( true ) | ||
283 | { | ||
284 | chr = getChar(); | ||
285 | if( isws( chr ) || chr == '/' || chr == '>' ) | ||
286 | { | ||
287 | addProperty( fbName.getData(), fbValue.getData() ); | ||
288 | return true; | ||
289 | } | ||
290 | else | ||
291 | { | ||
292 | if( chr == '&' ) | ||
293 | { | ||
294 | chr = getEscape(); | ||
295 | if( chr == '\0' ) return false; | ||
296 | fbValue.appendData( chr ); | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | fbValue.appendData( chr ); | ||
301 | usedChar(); | ||
302 | } | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | reportError("Expected an equals to seperate the params."); | ||
310 | return false; | ||
311 | } | ||
312 | |||
313 | return true; | ||
314 | } | ||
315 | |||
316 | bool XmlReader::content() | ||
317 | { | ||
318 | FlexBuf fbContent; | ||
319 | |||
320 | if( bStrip ) gcall( ws() ); | ||
321 | |||
322 | while( true ) | ||
323 | { | ||
324 | char chr = getChar(); | ||
325 | if( chr == '<' ) | ||
326 | { | ||
327 | if( getChar(1) == '/' ) | ||
328 | { | ||
329 | if( fbContent.getLength() > 0 ) | ||
330 | { | ||
331 | if( bStrip ) | ||
332 | { | ||
333 | int j; | ||
334 | for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); | ||
335 | ((char *)fbContent.getData())[j+1] = '\0'; | ||
336 | } | ||
337 | setContent( fbContent.getData() ); | ||
338 | } | ||
339 | usedChar(); | ||
340 | usedChar(); | ||
341 | gcall( ws() ); | ||
342 | FlexBuf fbName; | ||
343 | while( true ) | ||
344 | { | ||
345 | chr = getChar(); | ||
346 | if( isws( chr ) || chr == '>' ) | ||
347 | { | ||
348 | if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) | ||
349 | { | ||
350 | closeNode(); | ||
351 | break; | ||
352 | } | ||
353 | else | ||
354 | { | ||
355 | reportError("Mismatched close tag found."); | ||
356 | return false; | ||
357 | } | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | fbName.appendData( chr ); | ||
362 | usedChar(); | ||
363 | } | ||
364 | } | ||
365 | gcall( ws() ); | ||
366 | if( getChar() == '>' ) | ||
367 | { | ||
368 | usedChar(); | ||
369 | return true; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | reportError("Malformed close tag."); | ||
374 | return false; | ||
375 | } | ||
376 | } | ||
377 | else | ||
378 | { | ||
379 | if( fbContent.getLength() > 0 ) | ||
380 | { | ||
381 | if( bStrip ) | ||
382 | { | ||
383 | int j; | ||
384 | for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); | ||
385 | ((char *)fbContent.getData())[j+1] = '\0'; | ||
386 | } | ||
387 | setContent( fbContent.getData() ); | ||
388 | fbContent.clearData(); | ||
389 | } | ||
390 | gcall( node() ); | ||
391 | } | ||
392 | |||
393 | if( bStrip ) gcall( ws() ); | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | fbContent.appendData( chr ); | ||
398 | usedChar(); | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | |||
403 | void XmlReader::reportError( const char *sError ) | ||
404 | { | ||
405 | printf("XmlReader error: %s\n", sError ); | ||
406 | } | ||
407 | |||
408 | int XmlReader::getError() | ||
409 | { | ||
410 | return nError; | ||
411 | } | ||
412 | |||
diff --git a/src/xmlreader.h b/src/xmlreader.h new file mode 100644 index 0000000..a8a81f0 --- /dev/null +++ b/src/xmlreader.h | |||
@@ -0,0 +1,133 @@ | |||
1 | #ifndef XMLREADER | ||
2 | #define XMLREADER | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "xmldocument.h" | ||
6 | #include "flexbuf.h" | ||
7 | |||
8 | /** | ||
9 | * Takes care of reading in xml formatted data from a file. This could/should | ||
10 | * be made more arbitrary in the future so that we can read the data from any | ||
11 | * source. This is actually made quite simple already since all data read in | ||
12 | * is handled by one single helper function and then palced into a FlexBuf for | ||
13 | * easy access by the other functions. The FlexBuf also allows for block | ||
14 | * reading from disk, which improves speed by a noticable amount. | ||
15 | * <br> | ||
16 | * There are also some extra features implemented that allow you to break the | ||
17 | * standard XML reader specs and eliminate leading and trailing whitespace in | ||
18 | * all read content. This is useful in situations where you allow additional | ||
19 | * whitespace in the files to make them easily human readable. The resturned | ||
20 | * content will be NULL in sitautions where all content between nodes was | ||
21 | * stripped. | ||
22 | *@author Mike Buland | ||
23 | */ | ||
24 | class XmlReader : public XmlDocument | ||
25 | { | ||
26 | public: | ||
27 | /** | ||
28 | * Create a standard XmlReader. The optional parameter bStrip allows you to | ||
29 | * create a reader that will strip out all leading and trailing whitespace | ||
30 | * in content, a-la html. | ||
31 | *@param bStrip Strip out leading and trailing whitespace? | ||
32 | */ | ||
33 | XmlReader( bool bStrip=false ); | ||
34 | |||
35 | /** | ||
36 | * Destroy this XmlReader. | ||
37 | */ | ||
38 | ~XmlReader(); | ||
39 | |||
40 | /** | ||
41 | * Get the error code if an error happened. | ||
42 | *@returns The error code (I don't know what they are either) | ||
43 | */ | ||
44 | int getError(); | ||
45 | |||
46 | /** | ||
47 | * Report an error to something, this is a really strange mechanism and | ||
48 | * should probably just be replaced with the multi-log system. | ||
49 | *@param sError The error to report. | ||
50 | */ | ||
51 | void reportError( const char *sError ); | ||
52 | |||
53 | /** | ||
54 | * Build a document based on some kind of input. This is called | ||
55 | * automatically by the constructor. | ||
56 | */ | ||
57 | bool buildDoc(); | ||
58 | |||
59 | private: | ||
60 | /** | ||
61 | * This is called by the low level automoton in order to get the next | ||
62 | * character. This function should return a character at the current | ||
63 | * position plus nIndex, but does not increment the current character. | ||
64 | *@param nIndex The index of the character from the current stream position. | ||
65 | *@returns A single character at the requested position, or 0 for end of | ||
66 | * stream. | ||
67 | */ | ||
68 | virtual char getChar( int nIndex = 0 ) = 0; | ||
69 | |||
70 | /** | ||
71 | * Called to increment the current stream position by a single character. | ||
72 | */ | ||
73 | virtual void usedChar() = 0; | ||
74 | |||
75 | /** | ||
76 | * Automoton function: is whitespace. | ||
77 | *@param chr A character | ||
78 | *@returns True if chr is whitespace, false otherwise. | ||
79 | */ | ||
80 | bool isws( char chr ); | ||
81 | |||
82 | /** | ||
83 | * Automoton function: ws. Skips sections of whitespace. | ||
84 | *@returns True if everything was ok, False for end of stream. | ||
85 | */ | ||
86 | bool ws(); | ||
87 | |||
88 | /** | ||
89 | * Automoton function: node. Processes an XmlNode | ||
90 | *@returns True if everything was ok, False for end of stream. | ||
91 | */ | ||
92 | bool node(); | ||
93 | |||
94 | /** | ||
95 | * Automoton function: startNode. Processes the begining of a node. | ||
96 | *@returns True if everything was ok, False for end of stream. | ||
97 | */ | ||
98 | bool startNode(); | ||
99 | |||
100 | /** | ||
101 | * Automoton function: name. Processes the name of a node. | ||
102 | *@returns True if everything was ok, False for end of stream. | ||
103 | */ | ||
104 | bool name(); | ||
105 | |||
106 | char getEscape(); | ||
107 | |||
108 | /** | ||
109 | * Automoton function: paramlist. Processes a list of node params. | ||
110 | *@returns True if everything was ok, False for end of stream. | ||
111 | */ | ||
112 | bool paramlist(); | ||
113 | |||
114 | /** | ||
115 | * Automoton function: param. Processes a single parameter. | ||
116 | *@returns True if everything was ok, False for end of stream. | ||
117 | */ | ||
118 | bool param(); | ||
119 | |||
120 | /** | ||
121 | * Automoton function: content. Processes node content. | ||
122 | *@returns True if everything was ok, False for end of stream. | ||
123 | */ | ||
124 | bool content(); | ||
125 | |||
126 | FlexBuf fbContent; /**< buffer for the current node's content. */ | ||
127 | FlexBuf fbParamName; /**< buffer for the current param's name. */ | ||
128 | FlexBuf fbParamValue; /**< buffer for the current param's value. */ | ||
129 | bool bStrip; /**< Are we stripping whitespace? */ | ||
130 | int nError; /**< Is there an error? */ | ||
131 | }; | ||
132 | |||
133 | #endif | ||
diff --git a/src/xmlstringreader.cpp b/src/xmlstringreader.cpp new file mode 100644 index 0000000..aa7174f --- /dev/null +++ b/src/xmlstringreader.cpp | |||
@@ -0,0 +1,37 @@ | |||
1 | #include "xmlstringreader.h" | ||
2 | #include <string.h> | ||
3 | |||
4 | XmlStringReader::XmlStringReader( const char *sString, bool bStrip ) | ||
5 | : XmlReader( bStrip ) | ||
6 | { | ||
7 | this->sString = sString; | ||
8 | |||
9 | nIndex = 0; | ||
10 | nLength = strlen( sString ); | ||
11 | |||
12 | buildDoc(); | ||
13 | } | ||
14 | |||
15 | XmlStringReader::~XmlStringReader() | ||
16 | { | ||
17 | } | ||
18 | |||
19 | char XmlStringReader::getChar( int nAdd ) | ||
20 | { | ||
21 | if( nLength >= nIndex+nAdd+1 ) | ||
22 | { | ||
23 | return sString[nIndex+nAdd]; | ||
24 | } | ||
25 | else | ||
26 | { | ||
27 | return '\0'; | ||
28 | } | ||
29 | } | ||
30 | |||
31 | void XmlStringReader::usedChar() | ||
32 | { | ||
33 | if( nLength >= nIndex+1 ) | ||
34 | { | ||
35 | nIndex++; | ||
36 | } | ||
37 | } | ||
diff --git a/src/xmlstringreader.h b/src/xmlstringreader.h new file mode 100644 index 0000000..07da83c --- /dev/null +++ b/src/xmlstringreader.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef XMLSTRINGREADER | ||
2 | #define XMLSTRINGREADER | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include "xmlreader.h" | ||
6 | #include "flexbuf.h" | ||
7 | |||
8 | /** | ||
9 | * Takes care of reading in xml formatted data from a file. This could/should | ||
10 | * be made more arbitrary in the future so that we can read the data from any | ||
11 | * source. This is actually made quite simple already since all data read in | ||
12 | * is handled by one single helper function and then palced into a FlexBuf for | ||
13 | * easy access by the other functions. The FlexBuf also allows for block | ||
14 | * reading from disk, which improves speed by a noticable amount. | ||
15 | * <br> | ||
16 | * There are also some extra features implemented that allow you to break the | ||
17 | * standard XML reader specs and eliminate leading and trailing whitespace in | ||
18 | * all read content. This is useful in situations where you allow additional | ||
19 | * whitespace in the files to make them easily human readable. The resturned | ||
20 | * content will be NULL in sitautions where all content between nodes was | ||
21 | * stripped. | ||
22 | *@author Mike Buland | ||
23 | */ | ||
24 | class XmlStringReader : public XmlReader | ||
25 | { | ||
26 | public: | ||
27 | /** | ||
28 | * Create a new string reader around an already created and formatted | ||
29 | * null-terminated string. | ||
30 | *@param sString A pointer to the string data that will be used. This data | ||
31 | * is not changed during processing. | ||
32 | *@param bStrip Strip out leading and trailing whitespace. | ||
33 | */ | ||
34 | XmlStringReader( const char *sString, bool bStrip=false ); | ||
35 | |||
36 | /** | ||
37 | * Destroy this string reader. | ||
38 | */ | ||
39 | ~XmlStringReader(); | ||
40 | |||
41 | private: | ||
42 | char getChar( int nIndex = 0 ); | ||
43 | void usedChar(); | ||
44 | const char *sString; /**< Internal pointer to the input string. */ | ||
45 | int nIndex; /**< Our index into the string */ | ||
46 | int nLength; /**< The computed length of the string */ | ||
47 | }; | ||
48 | |||
49 | #endif | ||
diff --git a/src/xmlstringwriter.cpp b/src/xmlstringwriter.cpp new file mode 100644 index 0000000..adeed6a --- /dev/null +++ b/src/xmlstringwriter.cpp | |||
@@ -0,0 +1,23 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlstringwriter.h" | ||
4 | |||
5 | XmlStringWriter::XmlStringWriter( const char *sIndent ) : | ||
6 | XmlWriter( sIndent ) | ||
7 | { | ||
8 | } | ||
9 | |||
10 | XmlStringWriter::~XmlStringWriter() | ||
11 | { | ||
12 | } | ||
13 | |||
14 | void XmlStringWriter::writeString( const char *sString ) | ||
15 | { | ||
16 | sXml += sString; | ||
17 | } | ||
18 | |||
19 | std::string &XmlStringWriter::getString() | ||
20 | { | ||
21 | return sXml; | ||
22 | } | ||
23 | |||
diff --git a/src/xmlstringwriter.h b/src/xmlstringwriter.h new file mode 100644 index 0000000..530db3e --- /dev/null +++ b/src/xmlstringwriter.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef XML_STRING_WRITER | ||
2 | #define XML_STRING_WRITER | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | #include "xmlwriter.h" | ||
6 | |||
7 | /** | ||
8 | * Implements xml writing in the XML standard format. Also allows you to | ||
9 | * break that format and auto-indent your exported xml data for ease of | ||
10 | * reading. The auto-indenting will only be applied to sections that | ||
11 | * have no content of their own already. This means that except for | ||
12 | * whitespace all of your data will be preserved perfectly. | ||
13 | * You can create an XmlWriter object around a file, or access the static | ||
14 | * write function directly and just hand it a filename and a root XmlNode. | ||
15 | * When using an XmlWriter object the interface is identicle to that of | ||
16 | * the XmlDocument class, so reference that class for API info. However | ||
17 | * when the initial (or root) node is closed, and the document is finished | ||
18 | * the file will be created and written to automatically. The user can | ||
19 | * check to see if this is actually true by calling the isFinished | ||
20 | * function in the XmlDocument class. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class XmlStringWriter : public XmlWriter | ||
24 | { | ||
25 | public: | ||
26 | /** | ||
27 | * Construct a string writer using an internal string buffer. | ||
28 | *@param sIndent Optional indent to add to each line. | ||
29 | */ | ||
30 | XmlStringWriter( const char *sIndent=NULL ); | ||
31 | |||
32 | /** | ||
33 | * Destroy the string writer and the internal string. | ||
34 | */ | ||
35 | ~XmlStringWriter(); | ||
36 | |||
37 | /** | ||
38 | * Get the string that was built. This is only valid after the document has | ||
39 | * been completed, so check isCompleted or be sure your addNode and | ||
40 | * closeNode calls match up. | ||
41 | *@returns A reference to the internal string object. | ||
42 | */ | ||
43 | std::string &getString(); | ||
44 | |||
45 | private: | ||
46 | void writeString( const char *sString ); | ||
47 | std::string sXml; /**< The string object we "write" to. */ | ||
48 | }; | ||
49 | |||
50 | #endif | ||
diff --git a/src/xmlwriter.cpp b/src/xmlwriter.cpp new file mode 100644 index 0000000..236939d --- /dev/null +++ b/src/xmlwriter.cpp | |||
@@ -0,0 +1,173 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "xmlwriter.h" | ||
4 | |||
5 | XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : | ||
6 | XmlDocument( pRoot ) | ||
7 | { | ||
8 | if( sIndent == NULL ) | ||
9 | { | ||
10 | this->sIndent = ""; | ||
11 | } | ||
12 | else | ||
13 | { | ||
14 | this->sIndent = sIndent; | ||
15 | } | ||
16 | } | ||
17 | |||
18 | XmlWriter::~XmlWriter() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | void XmlWriter::write() | ||
23 | { | ||
24 | write( getRoot(), sIndent.c_str() ); | ||
25 | } | ||
26 | |||
27 | void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) | ||
28 | { | ||
29 | writeNode( pRoot, 0, sIndent ); | ||
30 | } | ||
31 | |||
32 | void XmlWriter::closeNode() | ||
33 | { | ||
34 | XmlDocument::closeNode(); | ||
35 | |||
36 | if( isCompleted() ) | ||
37 | { | ||
38 | write( getRoot(), sIndent.c_str() ); | ||
39 | } | ||
40 | } | ||
41 | |||
42 | void XmlWriter::writeIndent( int nIndent, const char *sIndent ) | ||
43 | { | ||
44 | if( sIndent == NULL ) return; | ||
45 | for( int j = 0; j < nIndent; j++ ) | ||
46 | { | ||
47 | writeString( sIndent ); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | std::string XmlWriter::escape( std::string sIn ) | ||
52 | { | ||
53 | std::string sOut; | ||
54 | |||
55 | std::string::const_iterator i; | ||
56 | for( i = sIn.begin(); i != sIn.end(); i++ ) | ||
57 | { | ||
58 | if( ((*i >= ' ' && *i <= '9') || | ||
59 | (*i >= 'a' && *i <= 'z') || | ||
60 | (*i >= 'A' && *i <= 'Z') ) && | ||
61 | (*i != '\"' && *i != '\'' ) | ||
62 | ) | ||
63 | { | ||
64 | sOut += *i; | ||
65 | } | ||
66 | else | ||
67 | { | ||
68 | sOut += "&#"; | ||
69 | char buf[4]; | ||
70 | sprintf( buf, "%d", *i ); | ||
71 | sOut += buf; | ||
72 | sOut += ';'; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | return sOut; | ||
77 | } | ||
78 | |||
79 | void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) | ||
80 | { | ||
81 | for( int j = 0; j < pNode->getNumProperties(); j++ ) | ||
82 | { | ||
83 | writeString(" "); | ||
84 | writeString( pNode->getPropertyName( j ) ); | ||
85 | writeString("=\""); | ||
86 | writeString( escape( pNode->getProperty( j ) ).c_str() ); | ||
87 | writeString("\""); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) | ||
92 | { | ||
93 | if( pNode->hasChildren() ) | ||
94 | { | ||
95 | writeIndent( nIndent, sIndent ); | ||
96 | writeString("<"); | ||
97 | writeString( pNode->getName() ); | ||
98 | writeNodeProps( pNode, nIndent, sIndent ); | ||
99 | if( sIndent ) | ||
100 | writeString(">\n"); | ||
101 | else | ||
102 | writeString(">"); | ||
103 | |||
104 | if( pNode->getContent( 0 ) ) | ||
105 | { | ||
106 | writeIndent( nIndent+1, sIndent ); | ||
107 | if( sIndent ) | ||
108 | { | ||
109 | writeString( pNode->getContent( 0 ) ); | ||
110 | writeString("\n"); | ||
111 | } | ||
112 | else | ||
113 | writeString( pNode->getContent( 0 ) ); | ||
114 | } | ||
115 | |||
116 | int nNumChildren = pNode->getNumChildren(); | ||
117 | for( int j = 0; j < nNumChildren; j++ ) | ||
118 | { | ||
119 | writeNode( pNode->getChild( j ), nIndent+1, sIndent ); | ||
120 | if( pNode->getContent( j+1 ) ) | ||
121 | { | ||
122 | writeIndent( nIndent+1, sIndent ); | ||
123 | if( sIndent ) | ||
124 | { | ||
125 | writeString( pNode->getContent( j+1 ) ); | ||
126 | writeString("\n"); | ||
127 | } | ||
128 | else | ||
129 | writeString( pNode->getContent( j+1 ) ); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | writeIndent( nIndent, sIndent ); | ||
134 | if( sIndent ) | ||
135 | { | ||
136 | writeString("</"); | ||
137 | writeString( pNode->getName() ); | ||
138 | writeString(">\n"); | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | writeString("</"); | ||
143 | writeString( pNode->getName() ); | ||
144 | writeString(">"); | ||
145 | } | ||
146 | } | ||
147 | else if( pNode->getContent() ) | ||
148 | { | ||
149 | writeIndent( nIndent, sIndent ); | ||
150 | writeString("<"); | ||
151 | writeString( pNode->getName() ); | ||
152 | writeNodeProps( pNode, nIndent, sIndent ); | ||
153 | writeString(">"); | ||
154 | writeString( pNode->getContent() ); | ||
155 | writeString("</"); | ||
156 | writeString( pNode->getName() ); | ||
157 | writeString(">"); | ||
158 | if( sIndent ) | ||
159 | writeString("\n"); | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | writeIndent( nIndent, sIndent ); | ||
164 | writeString("<"); | ||
165 | writeString( pNode->getName() ); | ||
166 | writeNodeProps( pNode, nIndent, sIndent ); | ||
167 | if( sIndent ) | ||
168 | writeString("/>\n"); | ||
169 | else | ||
170 | writeString("/>"); | ||
171 | } | ||
172 | } | ||
173 | |||
diff --git a/src/xmlwriter.h b/src/xmlwriter.h new file mode 100644 index 0000000..5bc3f0a --- /dev/null +++ b/src/xmlwriter.h | |||
@@ -0,0 +1,96 @@ | |||
1 | #ifndef XMLWRITER | ||
2 | #define XMLWRITER | ||
3 | |||
4 | #include "xmlnode.h" | ||
5 | #include "xmldocument.h" | ||
6 | |||
7 | /** | ||
8 | * Implements xml writing in the XML standard format. Also allows you to | ||
9 | * break that format and auto-indent your exported xml data for ease of | ||
10 | * reading. The auto-indenting will only be applied to sections that | ||
11 | * have no content of their own already. This means that except for | ||
12 | * whitespace all of your data will be preserved perfectly. | ||
13 | * You can create an XmlWriter object around a file, or access the static | ||
14 | * write function directly and just hand it a filename and a root XmlNode. | ||
15 | * When using an XmlWriter object the interface is identicle to that of | ||
16 | * the XmlDocument class, so reference that class for API info. However | ||
17 | * when the initial (or root) node is closed, and the document is finished | ||
18 | * the file will be created and written to automatically. The user can | ||
19 | * check to see if this is actually true by calling the isFinished | ||
20 | * function in the XmlDocument class. | ||
21 | *@author Mike Buland | ||
22 | */ | ||
23 | class XmlWriter : public XmlDocument | ||
24 | { | ||
25 | public: | ||
26 | /** | ||
27 | * Construct a standard XmlWriter. | ||
28 | *@param sIndent Set this to something other than NULL to include it as an | ||
29 | * indent before each node in the output that doesn't already have content. | ||
30 | * If you are using the whitespace stripping option in the XmlReader and set | ||
31 | * this to a tab or some spaces it will never effect the content of your | ||
32 | * file. | ||
33 | */ | ||
34 | XmlWriter( const char *sIndent=NULL, XmlNode *pRoot=NULL ); | ||
35 | |||
36 | /** | ||
37 | * Destroy the writer. | ||
38 | */ | ||
39 | ~XmlWriter(); | ||
40 | |||
41 | /** | ||
42 | * This override of the parent class closeNode function calls the parent | ||
43 | * class, but also triggers a write operation when the final node is closed. | ||
44 | * This means that by checking the isCompleted() function the user may also | ||
45 | * check to see if their file has been written or not. | ||
46 | */ | ||
47 | void closeNode(); | ||
48 | |||
49 | void write(); | ||
50 | |||
51 | private: | ||
52 | std::string sIndent; /**< The indent string */ | ||
53 | |||
54 | std::string escape( std::string sIn ); | ||
55 | |||
56 | /** | ||
57 | * Write the file. | ||
58 | *@param pNode The root node | ||
59 | *@param sIndent The indent text. | ||
60 | */ | ||
61 | void write( XmlNode *pNode, const char *sIndent=NULL ); | ||
62 | |||
63 | /** | ||
64 | * Write a node in the file, including children. | ||
65 | *@param pNode The node to write. | ||
66 | *@param nIndent The indent level (the number of times to include sIndent) | ||
67 | *@param sIndent The indent text. | ||
68 | */ | ||
69 | void writeNode( XmlNode *pNode, int nIndent, const char *sIndent ); | ||
70 | |||
71 | /** | ||
72 | * Write the properties of a node. | ||
73 | *@param pNode The node who's properties to write. | ||
74 | *@param nIndent The indent level of the containing node | ||
75 | *@param sIndent The indent text. | ||
76 | */ | ||
77 | void writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ); | ||
78 | |||
79 | /** | ||
80 | * Called to write the actual indent. | ||
81 | *@param nIndent The indent level. | ||
82 | *@param sIndent The indent text. | ||
83 | */ | ||
84 | void writeIndent( int nIndent, const char *sIndent ); | ||
85 | |||
86 | /** | ||
87 | * This is the function that must be overridden in order to use this class. | ||
88 | * It must write the null-terminated string sString, minus the mull, | ||
89 | * verbatum to it's output device. Adding extra characters for any reason | ||
90 | * will break the XML formatting. | ||
91 | *@param sString The string data to write to the output. | ||
92 | */ | ||
93 | virtual void writeString( const char *sString ) = 0; | ||
94 | }; | ||
95 | |||
96 | #endif | ||