PR c++/3637
[official-gcc.git] / gcc / ada / g-cgicoo.adb
blobf28832a0d361b7ffec7b9750ce6921619ca24dca
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G N A T . C G I . C O O K I E --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision: 1.4 $
10 -- --
11 -- Copyright (C) 2000-2001 Ada Core Technologies, Inc.
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
30 -- --
31 -- GNAT is maintained by Ada Core Technologies Inc (http://www.gnat.com). --
32 -- --
33 ------------------------------------------------------------------------------
35 with Ada.Strings.Fixed;
36 with Ada.Strings.Maps;
37 with Ada.Text_IO;
38 with Ada.Integer_Text_IO;
40 with GNAT.Table;
42 package body GNAT.CGI.Cookie is
44 use Ada;
46 Valid_Environment : Boolean := False;
47 -- This boolean will be set to True if the initialization was fine.
49 Header_Sent : Boolean := False;
50 -- Will be set to True when the header will be sent.
52 -- Cookie data that have been added.
54 type String_Access is access String;
56 type Cookie_Data is record
57 Key : String_Access;
58 Value : String_Access;
59 Comment : String_Access;
60 Domain : String_Access;
61 Max_Age : Natural;
62 Path : String_Access;
63 Secure : Boolean := False;
64 end record;
66 type Key_Value is record
67 Key, Value : String_Access;
68 end record;
70 package Cookie_Table is new Table (Cookie_Data, Positive, 1, 5, 50);
71 -- This is the table to keep all cookies to be sent back to the server.
73 package Key_Value_Table is new Table (Key_Value, Positive, 1, 1, 50);
74 -- This is the table to keep all cookies received from the server.
76 procedure Check_Environment;
77 pragma Inline (Check_Environment);
78 -- This procedure will raise Data_Error if Valid_Environment is False.
80 procedure Initialize;
81 -- Initialize CGI package by reading the runtime environment. This
82 -- procedure is called during elaboration. All exceptions raised during
83 -- this procedure are deferred.
85 -----------------------
86 -- Check_Environment --
87 -----------------------
89 procedure Check_Environment is
90 begin
91 if not Valid_Environment then
92 raise Data_Error;
93 end if;
94 end Check_Environment;
96 -----------
97 -- Count --
98 -----------
100 function Count return Natural is
101 begin
102 return Key_Value_Table.Last;
103 end Count;
105 ------------
106 -- Exists --
107 ------------
109 function Exists (Key : String) return Boolean is
110 begin
111 Check_Environment;
113 for K in 1 .. Key_Value_Table.Last loop
114 if Key_Value_Table.Table (K).Key.all = Key then
115 return True;
116 end if;
117 end loop;
119 return False;
120 end Exists;
122 ----------------------
123 -- For_Every_Cookie --
124 ----------------------
126 procedure For_Every_Cookie is
127 Quit : Boolean;
129 begin
130 Check_Environment;
132 for K in 1 .. Key_Value_Table.Last loop
133 Quit := False;
135 Action (Key_Value_Table.Table (K).Key.all,
136 Key_Value_Table.Table (K).Value.all,
138 Quit);
140 exit when Quit;
141 end loop;
142 end For_Every_Cookie;
144 ----------------
145 -- Initialize --
146 ----------------
148 procedure Initialize is
150 HTTP_COOKIE : constant String := Metavariable (CGI.HTTP_Cookie);
152 procedure Set_Parameter_Table (Data : String);
153 -- Parse Data and insert information in Key_Value_Table.
155 -------------------------
156 -- Set_Parameter_Table --
157 -------------------------
159 procedure Set_Parameter_Table (Data : String) is
161 procedure Add_Parameter (K : Positive; P : String);
162 -- Add a single parameter into the table at index K. The parameter
163 -- format is "key=value".
165 Count : constant Positive
166 := 1 + Strings.Fixed.Count (Data, Strings.Maps.To_Set (";"));
167 -- Count is the number of parameters in the string. Parameters are
168 -- separated by ampersand character.
170 Index : Positive := Data'First;
171 Sep : Natural;
173 -------------------
174 -- Add_Parameter --
175 -------------------
177 procedure Add_Parameter (K : Positive; P : String) is
178 Equal : constant Natural := Strings.Fixed.Index (P, "=");
179 begin
180 if Equal = 0 then
181 raise Data_Error;
182 else
183 Key_Value_Table.Table (K) :=
184 Key_Value'(new String'(Decode (P (P'First .. Equal - 1))),
185 new String'(Decode (P (Equal + 1 .. P'Last))));
186 end if;
187 end Add_Parameter;
189 begin
190 Key_Value_Table.Set_Last (Count);
192 for K in 1 .. Count - 1 loop
193 Sep := Strings.Fixed.Index (Data (Index .. Data'Last), ";");
195 Add_Parameter (K, Data (Index .. Sep - 1));
197 Index := Sep + 2;
198 end loop;
200 -- add last parameter
202 Add_Parameter (Count, Data (Index .. Data'Last));
203 end Set_Parameter_Table;
205 begin
206 if HTTP_COOKIE /= "" then
207 Set_Parameter_Table (HTTP_COOKIE);
208 end if;
210 Valid_Environment := True;
212 exception
213 when others =>
214 Valid_Environment := False;
215 end Initialize;
217 ---------
218 -- Key --
219 ---------
221 function Key (Position : Positive) return String is
222 begin
223 Check_Environment;
225 if Position <= Key_Value_Table.Last then
226 return Key_Value_Table.Table (Position).Key.all;
227 else
228 raise Cookie_Not_Found;
229 end if;
230 end Key;
232 --------
233 -- Ok --
234 --------
236 function Ok return Boolean is
237 begin
238 return Valid_Environment;
239 end Ok;
241 ----------------
242 -- Put_Header --
243 ----------------
245 procedure Put_Header
246 (Header : String := Default_Header;
247 Force : Boolean := False)
250 procedure Output_Cookies;
251 -- Iterate through the list of cookies to be sent to the server
252 -- and output them.
254 --------------------
255 -- Output_Cookies --
256 --------------------
258 procedure Output_Cookies is
260 procedure Output_One_Cookie
261 (Key : String;
262 Value : String;
263 Comment : String;
264 Domain : String;
265 Max_Age : Natural;
266 Path : String;
267 Secure : Boolean);
268 -- Output one cookie in the CGI header.
270 -----------------------
271 -- Output_One_Cookie --
272 -----------------------
274 procedure Output_One_Cookie
275 (Key : String;
276 Value : String;
277 Comment : String;
278 Domain : String;
279 Max_Age : Natural;
280 Path : String;
281 Secure : Boolean)
283 begin
284 Text_IO.Put ("Set-Cookie: ");
285 Text_IO.Put (Key & '=' & Value);
287 if Comment /= "" then
288 Text_IO.Put ("; Comment=" & Comment);
289 end if;
291 if Domain /= "" then
292 Text_IO.Put ("; Domain=" & Domain);
293 end if;
295 if Max_Age /= Natural'Last then
296 Text_IO.Put ("; Max-Age=");
297 Integer_Text_IO.Put (Max_Age, Width => 0);
298 end if;
300 if Path /= "" then
301 Text_IO.Put ("; Path=" & Path);
302 end if;
304 if Secure then
305 Text_IO.Put ("; Secure");
306 end if;
308 Text_IO.New_Line;
309 end Output_One_Cookie;
311 -- Start of processing for Output_Cookies
313 begin
314 for C in 1 .. Cookie_Table.Last loop
315 Output_One_Cookie (Cookie_Table.Table (C).Key.all,
316 Cookie_Table.Table (C).Value.all,
317 Cookie_Table.Table (C).Comment.all,
318 Cookie_Table.Table (C).Domain.all,
319 Cookie_Table.Table (C).Max_Age,
320 Cookie_Table.Table (C).Path.all,
321 Cookie_Table.Table (C).Secure);
322 end loop;
323 end Output_Cookies;
325 -- Start of processing for Put_Header
327 begin
328 if Header_Sent = False or else Force then
329 Check_Environment;
330 Text_IO.Put_Line (Header);
331 Output_Cookies;
332 Text_IO.New_Line;
333 Header_Sent := True;
334 end if;
335 end Put_Header;
337 ---------
338 -- Set --
339 ---------
341 procedure Set
342 (Key : String;
343 Value : String;
344 Comment : String := "";
345 Domain : String := "";
346 Max_Age : Natural := Natural'Last;
347 Path : String := "/";
348 Secure : Boolean := False) is
349 begin
350 Cookie_Table.Increment_Last;
352 Cookie_Table.Table (Cookie_Table.Last) :=
353 Cookie_Data'(new String'(Key),
354 new String'(Value),
355 new String'(Comment),
356 new String'(Domain),
357 Max_Age,
358 new String'(Path),
359 Secure);
360 end Set;
362 -----------
363 -- Value --
364 -----------
366 function Value
367 (Key : String;
368 Required : Boolean := False)
369 return String
371 begin
372 Check_Environment;
374 for K in 1 .. Key_Value_Table.Last loop
375 if Key_Value_Table.Table (K).Key.all = Key then
376 return Key_Value_Table.Table (K).Value.all;
377 end if;
378 end loop;
380 if Required then
381 raise Cookie_Not_Found;
382 else
383 return "";
384 end if;
385 end Value;
387 function Value (Position : Positive) return String is
388 begin
389 Check_Environment;
391 if Position <= Key_Value_Table.Last then
392 return Key_Value_Table.Table (Position).Value.all;
393 else
394 raise Cookie_Not_Found;
395 end if;
396 end Value;
398 -- Elaboration code for package
400 begin
401 -- Initialize unit by reading the HTTP_COOKIE metavariable and fill
402 -- Key_Value_Table structure.
404 Initialize;
405 end GNAT.CGI.Cookie;