OSDN Git Service

* rtl.h (mem_attrs): Rename decl to expr; adjust all users.
[pf3gnuchains/gcc-fork.git] / gcc / ada / g-cgicoo.adb
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 ------------------------------------------------------------------------------
34
35 with Ada.Strings.Fixed;
36 with Ada.Strings.Maps;
37 with Ada.Text_IO;
38 with Ada.Integer_Text_IO;
39
40 with GNAT.Table;
41
42 package body GNAT.CGI.Cookie is
43
44    use Ada;
45
46    Valid_Environment : Boolean := False;
47    --  This boolean will be set to True if the initialization was fine.
48
49    Header_Sent : Boolean := False;
50    --  Will be set to True when the header will be sent.
51
52    --  Cookie data that have been added.
53
54    type String_Access is access String;
55
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;
65
66    type Key_Value is record
67       Key, Value : String_Access;
68    end record;
69
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.
72
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.
75
76    procedure Check_Environment;
77    pragma Inline (Check_Environment);
78    --  This procedure will raise Data_Error if Valid_Environment is False.
79
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.
84
85    -----------------------
86    -- Check_Environment --
87    -----------------------
88
89    procedure Check_Environment is
90    begin
91       if not Valid_Environment then
92          raise Data_Error;
93       end if;
94    end Check_Environment;
95
96    -----------
97    -- Count --
98    -----------
99
100    function Count return Natural is
101    begin
102       return Key_Value_Table.Last;
103    end Count;
104
105    ------------
106    -- Exists --
107    ------------
108
109    function Exists (Key : String) return Boolean is
110    begin
111       Check_Environment;
112
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;
118
119       return False;
120    end Exists;
121
122    ----------------------
123    -- For_Every_Cookie --
124    ----------------------
125
126    procedure For_Every_Cookie is
127       Quit : Boolean;
128
129    begin
130       Check_Environment;
131
132       for K in 1 .. Key_Value_Table.Last loop
133          Quit := False;
134
135          Action (Key_Value_Table.Table (K).Key.all,
136                  Key_Value_Table.Table (K).Value.all,
137                  K,
138                  Quit);
139
140          exit when Quit;
141       end loop;
142    end For_Every_Cookie;
143
144    ----------------
145    -- Initialize --
146    ----------------
147
148    procedure Initialize is
149
150       HTTP_COOKIE : constant String := Metavariable (CGI.HTTP_Cookie);
151
152       procedure Set_Parameter_Table (Data : String);
153       --  Parse Data and insert information in Key_Value_Table.
154
155       -------------------------
156       -- Set_Parameter_Table --
157       -------------------------
158
159       procedure Set_Parameter_Table (Data : String) is
160
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".
164
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.
169
170          Index : Positive := Data'First;
171          Sep   : Natural;
172
173          -------------------
174          -- Add_Parameter --
175          -------------------
176
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;
188
189       begin
190          Key_Value_Table.Set_Last (Count);
191
192          for K in 1 .. Count - 1 loop
193             Sep := Strings.Fixed.Index (Data (Index .. Data'Last), ";");
194
195             Add_Parameter (K, Data (Index .. Sep - 1));
196
197             Index := Sep + 2;
198          end loop;
199
200          --  add last parameter
201
202          Add_Parameter (Count, Data (Index .. Data'Last));
203       end Set_Parameter_Table;
204
205    begin
206       if HTTP_COOKIE /= "" then
207          Set_Parameter_Table (HTTP_COOKIE);
208       end if;
209
210       Valid_Environment := True;
211
212    exception
213       when others =>
214          Valid_Environment := False;
215    end Initialize;
216
217    ---------
218    -- Key --
219    ---------
220
221    function Key (Position : Positive) return String is
222    begin
223       Check_Environment;
224
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;
231
232    --------
233    -- Ok --
234    --------
235
236    function Ok return Boolean is
237    begin
238       return Valid_Environment;
239    end Ok;
240
241    ----------------
242    -- Put_Header --
243    ----------------
244
245    procedure Put_Header
246      (Header : String  := Default_Header;
247       Force  : Boolean := False)
248    is
249
250       procedure Output_Cookies;
251       --  Iterate through the list of cookies to be sent to the server
252       --  and output them.
253
254       --------------------
255       -- Output_Cookies --
256       --------------------
257
258       procedure Output_Cookies is
259
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.
269
270          -----------------------
271          -- Output_One_Cookie --
272          -----------------------
273
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)
282          is
283          begin
284             Text_IO.Put ("Set-Cookie: ");
285             Text_IO.Put (Key & '=' & Value);
286
287             if Comment /= "" then
288                Text_IO.Put ("; Comment=" & Comment);
289             end if;
290
291             if Domain /= "" then
292                Text_IO.Put ("; Domain=" & Domain);
293             end if;
294
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;
299
300             if Path /= "" then
301                Text_IO.Put ("; Path=" & Path);
302             end if;
303
304             if Secure then
305                Text_IO.Put ("; Secure");
306             end if;
307
308             Text_IO.New_Line;
309          end Output_One_Cookie;
310
311       --  Start of processing for Output_Cookies
312
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;
324
325    --  Start of processing for Put_Header
326
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;
336
337    ---------
338    -- Set --
339    ---------
340
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;
351
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;
361
362    -----------
363    -- Value --
364    -----------
365
366    function Value
367      (Key      : String;
368       Required : Boolean := False)
369       return     String
370    is
371    begin
372       Check_Environment;
373
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;
379
380       if Required then
381          raise Cookie_Not_Found;
382       else
383          return "";
384       end if;
385    end Value;
386
387    function Value (Position : Positive) return String is
388    begin
389       Check_Environment;
390
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;
397
398 --  Elaboration code for package
399
400 begin
401    --  Initialize unit by reading the HTTP_COOKIE metavariable and fill
402    --  Key_Value_Table structure.
403
404    Initialize;
405 end GNAT.CGI.Cookie;