1 #ifndef CGI___SESSION__HPP
2 #define CGI___SESSION__HPP
3
4 /* $Id: cgi_session.hpp 497034 2016-04-04 12:46:26Z dicuccio $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Maxim Didenko
30 *
31 */
32
33 /// @file cgi_session.hpp
34 /// API to store CGI session data between Web requests.
35
36 #include <corelib/ncbistd.hpp>
37
38 #include <memory>
39
40 /** @addtogroup CGI
41 *
42 * @{
43 */
44
45
46 BEGIN_NCBI_SCOPE
47
48 // fwd-decl
49 class ICgiSessionStorage;
50 class CCgiRequest;
51 class CCgiCookie;
52
53 /////////////////////////////////////////////////////////////////////////////
54 ///
55 /// CCgiSession --
56 ///
57 /// Facilitate the transfer of session ID between Web requests.
58 /// Store and retrieve the CGI session data from an external
59 /// data storage using the session ID.
60 ///
61 class NCBI_XCGI_EXPORT CCgiSession
62 {
63 public:
64 typedef list<string> TNames;
65
66 static const char* kDefaultSessionIdName;
67 static const char* kDefaultSessionCookieDomain;
68 static const char* kDefaultSessionCookiePath;
69
70 /// Session status
71 enum EStatus {
72 eNew, ///< The session has just been created
73 eLoaded, ///< The session is loaded
74 eNotLoaded, ///< The session has not been loaded yet
75 eDeleted, ///< The session is deleted
76 eImplNotSet ///< The CGI application didn't set the session
77 ///< implementation
78 };
79
80 /// Specifies if a client session cookie can be used to transfer
81 /// session id between requests
82 enum ECookieSupport {
83 eUseCookie, ///< A session cookie will be added to the response
84 eNoCookie ///< A session cookie will not be added to the response
85 };
86
87 CCgiSession(const CCgiRequest& request,
88 ICgiSessionStorage* impl,
89 EOwnership impl_ownership = eTakeOwnership,
90 ECookieSupport cookie_support = eUseCookie);
91
92 ~CCgiSession();
93
94 /// Get session ID.
95 /// @throw CCgiSessionException if session ID is not set and it
96 /// can not be retrieved from CGI request too.
97 const string& GetId(void) const;
98
99 /// Set session ID.
100 /// The previously loaded session (if any) will be closed.
101 void SetId(const string& session_id);
102
103 /// Modify session ID.
104 /// The session must be loaded before calling this method.
105 void ModifyId(const string& new_session_id);
106
107 /// Load the session.
108 /// @throw CCgiSessionException if session ID is not set and it
109 /// can not be retrieved from CGI request too.
110 void Load(void);
111
112 /// Create new session.
113 /// The previously loaded session (if any) will be closed.
114 void CreateNewSession(void);
115
116 /// Retrieve names of all attributes attached to this session.
117 /// @throw CCgiSessionException if the session is not loaded.
118 TNames GetAttributeNames(void) const;
119
120 /// Get input stream to read an attribute's data from.
121 /// @param[in] name
122 /// Name of the attribute
123 /// @param[out] size
124 /// Size of the attribute's data
125 /// @return
126 /// Stream to read attribute's data from.If the attribute does not exist,
127 /// then return an empty stream.
128 /// @throw CCgiSessionException if the session is not loaded.
129 CNcbiIstream& GetAttrIStream(const string& name, size_t* size = NULL);
130
131 /// Get output stream to write an attribute's data to.
132 /// If the attribute does not exist it will be created and added
133 /// to the session. If the attribute exists its content will be
134 /// overwritten.
135 /// @param[in] name
136 /// Name of the attribute
137 /// @throw CCgiSessionException if the session is not loaded.
138 CNcbiOstream& GetAttrOStream(const string& name);
139
140 /// Set attribute data as a string.
141 /// @param[in] name
142 /// Name of the attribute to set
143 /// @param[in] value
144 /// Value to set the attribute data to
145 /// @throw CCgiSessionException if the session is not loaded.
146 void SetAttribute(const string& name, const string& value);
147
148 /// Get attribute data as string.
149 /// @param[in] name
150 /// Name of the attribute to retrieve
151 /// @return
152 /// Data of the attribute, if set.
153 /// @throw CCgiSessionException with error code eNotLoaded
154 /// if the session has not been loaded yet;
155 /// CCgiSessionException with error code eAttrNotFound if
156 /// attribute with the specified name was not found;
157 /// CCgiSessionException with error code eImplException if
158 /// an error occured during attribute retrieval -- in the
159 /// latter case, more information can be obtained from the
160 /// embedded exception.
161 string GetAttribute(const string& name) const;
162
163 /// Remove attribute from the session.
164 /// @param[in] name
165 /// Name of the attribute to remove
166 /// @throw CCgiSessionException if the session is not loaded.
167 void RemoveAttribute(const string& name);
168
169 /// Delete current session
170 /// @throw CCgiSessionException if the session is not loaded.
171 void DeleteSession(void);
172
173 /// Get current status of the session.
174 EStatus GetStatus(void) const;
175
176 /// Check if this session object is valid.
177 /// @return True, if this session has been successfully loaded
178 /// or has just been created. False - if this session
179 /// does not exist and cannot be used.
180 bool Exists(void) const;
181
182 /// Get name for session ID.
183 /// @sa SetSessionIdName
184 const string& GetSessionIdName(void) const;
185
186 /// Set name for session ID.
187 /// This name is used as a cookie name for a session cookie.
188 void SetSessionIdName(const string& name);
189
190 /// Set session cookie domain
191 /// @sa SetSessionIdName
192 void SetSessionCookieDomain(const string& domain);
193
194 /// Set session cookie path
195 /// @sa SetSessionIdName
196 void SetSessionCookiePath(const string& path);
197
198 /// Set session cookie expiration time
199 void SetSessionCookieExpTime(const CTime& exp_time);
200
201 /// Get a cookie pertaining to the session. May create new cookie,
202 /// if needed and allowed to.
203 /// @return
204 /// Session CGI cookie;
205 /// NULL if no session is loaded or if cookie support is disabled.
206 const CCgiCookie* GetSessionCookie(void) const;
207
208 /// Retrieve a session id from a query string or a session cookie
209 string RetrieveSessionId() const;
210
211 private:
212 const CCgiRequest& m_Request;
213 ICgiSessionStorage* m_Impl;
214 unique_ptr<ICgiSessionStorage> m_ImplGuard;
215 ECookieSupport m_CookieSupport;
216
217 string m_SessionId;
218
219 string m_SessionIdName;
220 string m_SessionCookieDomain;
221 string m_SessionCookiePath;
222 CTime m_SessionCookieExpTime;
223 unique_ptr<CCgiCookie> m_SessionCookie;
224 EStatus m_Status;
225
226 void x_Load() const;
227 private:
228 CCgiSession(const CCgiSession&);
229 CCgiSession& operator=(const CCgiSession&);
230 };
231
Exists(void) const232 inline bool CCgiSession::Exists(void) const
233 {
234 return m_Status == eLoaded || m_Status == eNew;
235 }
236
237
238 /////////////////////////////////////////////////////////////////////////////
239 ///
240 /// ICgiSessionStorage --
241 ///
242 /// Implement data storage and retrieval for CCgiSession.
243 /// @sa CCgiSession
244 ///
245
246
247 class NCBI_XCGI_EXPORT ICgiSessionStorage
248 {
249 public:
250 typedef CCgiSession::TNames TNames;
251
252 virtual ~ICgiSessionStorage();
253
254 /// Create a new empty session.
255 /// @return ID of the new session
256 virtual string CreateNewSession() = 0;
257
258 /// Modify session id.
259 /// Change Id of the current session.
260 /// The implementations must handle binary data correctly (e.g.
261 /// NULL characters in the string).
262 virtual void ModifySessionId(const string& new_id) = 0;
263
264 /// Load the session
265 /// The implementations must handle binary data correctly (e.g.
266 /// NULL characters in the string).
267 /// @param[in]
268 /// ID of the session
269 /// @return true if the session was loaded, false otherwise
270 virtual bool LoadSession(const string& sessionid) = 0;
271
272 /// Retrieve names of all attributes attached to this session.
273 virtual TNames GetAttributeNames(void) const = 0;
274
275 /// Get input stream to read an attribute's data from.
276 /// @param[in] name
277 /// Name of the attribute
278 /// @param[out] size
279 /// Size of the attribute's data
280 /// @return
281 /// Stream to read attribute's data from.If the attribute does not exist,
282 /// then return an empty stream.
283 virtual CNcbiIstream& GetAttrIStream(const string& name,
284 size_t* size = 0) = 0;
285
286 /// Get output stream to write an attribute's data to.
287 /// If the attribute does not exist it will be created and added
288 /// to the session. If the attribute exists its content will be
289 /// overwritten.
290 /// @param[in] name
291 /// Name of the attribute
292 virtual CNcbiOstream& GetAttrOStream(const string& name) = 0;
293
294 /// Set attribute data as a string.
295 /// @param[in] name
296 /// Name of the attribute to set
297 /// @param[in] value
298 /// Value to set the attribute data to
299 virtual void SetAttribute(const string& name, const string& value) = 0;
300
301 /// Get attribute data as string.
302 /// @param[in] name
303 /// Name of the attribute to retrieve
304 /// @return
305 /// Data of the attribute, if set.
306 /// @throw CCgiSessionException with error code eNotLoaded
307 /// if the session has not been loaded yet;
308 /// CCgiSessionException with error code eAttrNotFound if
309 /// attribute with the specified name was not found;
310 /// CCgiSessionException with error code eImplException if
311 /// an error occured during attribute retrieval -- in the
312 /// latter case, more information can be obtained from the
313 /// embedded exception.
314 virtual string GetAttribute(const string& name) const = 0;
315
316 /// Remove attribute from the session.
317 /// @param[in] name
318 /// Name of the attribute to remove
319 virtual void RemoveAttribute(const string& name) = 0;
320
321 /// Delete current session
322 virtual void DeleteSession() = 0;
323
324 /// Reset the session. The an implementation should close
325 /// all input/ouptut streams here.
326 virtual void Reset() = 0;
327 };
328
329 /////////////////////////////////////////////////////////////////////
330
331 inline
GetStatus() const332 CCgiSession::EStatus CCgiSession::GetStatus() const
333 {
334 return m_Status;
335 }
336 inline
GetSessionIdName() const337 const string& CCgiSession::GetSessionIdName() const
338 {
339 return m_SessionIdName;
340 }
341 inline
SetSessionIdName(const string & name)342 void CCgiSession::SetSessionIdName(const string& name)
343 {
344 m_SessionIdName = name;
345 }
346 inline
SetSessionCookieDomain(const string & domain)347 void CCgiSession::SetSessionCookieDomain(const string& domain)
348 {
349 m_SessionCookieDomain = domain;
350 }
351 inline
SetSessionCookiePath(const string & path)352 void CCgiSession::SetSessionCookiePath(const string& path)
353 {
354 m_SessionCookiePath = path;
355 }
356 inline
SetSessionCookieExpTime(const CTime & exp_time)357 void CCgiSession::SetSessionCookieExpTime(const CTime& exp_time)
358 {
359 m_SessionCookieExpTime = exp_time;
360 }
361
362
363 END_NCBI_SCOPE
364
365
366 /* @} */
367
368 #endif /* CGI___SESSION__HPP */
369