ACE+TAO-7_0_10
[ACE_TAO.git] / ACE / websvcs / lib / URL_Addr.cpp
blob42d1e5a0827b1f8d54592c536bb04fbb034c1353
1 #include "URL_Addr.h"
3 #if !defined (__ACE_INLINE__)
4 #include "URL_Addr.inl"
5 #endif /* __ACE_INLINE__ */
7 #include "ace/Global_Macros.h"
8 #include "ace/OS_Memory.h"
9 #include "ace/OS_NS_strings.h"
10 #include "ace/OS_NS_stdio.h"
12 static ACE_TCHAR http[] = ACE_TEXT ("http:");
13 static size_t http_size = sizeof(http)/sizeof(http[0]) - 1;
14 static ACE_TCHAR ftp[] = ACE_TEXT ("ftp:");
15 static size_t ftp_size = sizeof(ftp)/sizeof(ftp[0]) - 1;
16 static ACE_TCHAR mailto[] = ACE_TEXT ("mailto:");
17 static size_t mailto_size = sizeof(mailto)/sizeof(mailto[0]) - 1;
19 static ACE_TCHAR file[] = ACE_TEXT ("file:");
20 static size_t file_size = sizeof(file)/sizeof(file[0]) - 1;
21 static ACE_TCHAR afs[] = ACE_TEXT ("afs:");
22 static size_t afs_size = sizeof(afs)/sizeof(afs[0]) - 1;
23 static ACE_TCHAR news[] = ACE_TEXT ("news:");
24 static size_t news_size = sizeof(news)/sizeof(news[0]) - 1;
25 static ACE_TCHAR nntp[] = ACE_TEXT ("nntp:");
26 static size_t nntp_size = sizeof(nntp)/sizeof(nntp[0]) - 1;
27 static ACE_TCHAR cid[] = ACE_TEXT ("cid:");
28 static size_t cid_size = sizeof(cid)/sizeof(cid[0]) - 1;
29 static ACE_TCHAR mid[] = ACE_TEXT ("mid:");
30 static size_t mid_size = sizeof(mid)/sizeof(mid[0]) - 1;
31 static ACE_TCHAR wais[] = ACE_TEXT ("wais:");
32 static size_t wais_size = sizeof(wais)/sizeof(wais[0]) - 1;
33 static ACE_TCHAR prospero[] = ACE_TEXT ("prospero:");
34 static size_t prospero_size = sizeof(prospero)/sizeof(prospero[0]) - 1;
35 static ACE_TCHAR telnet[] = ACE_TEXT ("telnet:");
36 static size_t telnet_size = sizeof(telnet)/sizeof(telnet[0]) - 1;
37 static ACE_TCHAR rlogin[] = ACE_TEXT ("rlogin:");
38 static size_t rlogin_size = sizeof(rlogin)/sizeof(rlogin[0]) - 1;
39 static ACE_TCHAR tn3270[] = ACE_TEXT ("tn3270:");
40 static size_t tn3270_size = sizeof(tn3270)/sizeof(tn3270[0]) - 1;
41 static ACE_TCHAR gopher[] = ACE_TEXT ("gopher:");
42 static size_t gopher_size = sizeof(gopher)/sizeof(gopher[0]) - 1;
44 ACE_URL_Addr::ACE_URL_Addr ()
45 : url_ (0)
49 ACE_URL_Addr::~ACE_URL_Addr ()
51 ACE_OS::free (this->url_);
52 this->url_ = 0;
55 int
56 ACE_URL_Addr::set (const ACE_URL_Addr& address)
58 return this->ACE_URL_Addr::string_to_addr (address.url_);
61 int
62 ACE_URL_Addr::string_to_addr (const ACE_TCHAR *address)
64 if (this->url_ != 0)
65 ACE_OS::free (this->url_);
66 if (address == 0)
67 return -1;
68 ACE_ALLOCATOR_RETURN (this->url_, ACE_OS::strdup (address), -1);
69 return 0;
72 int
73 ACE_URL_Addr::addr_to_string (ACE_TCHAR *s,
74 size_t size,
75 int) const
77 if (size < ACE_OS::strlen (this->url_))
78 return -1;
79 ACE_OS::strcpy (s, this->url_);
80 return 0;
83 int
84 ACE_URL_Addr::accept (ACE_URL_Addr_Visitor* visitor)
86 return visitor->visit (this);
89 // The factory method to create URL addresses.
90 ACE_URL_Addr*
91 ACE_URL_Addr::create_address (const ACE_TCHAR *url)
93 ACE_URL_Addr* addr = 0;
94 if (ACE_OS::strncasecmp (http, url, http_size) == 0)
95 ACE_NEW_RETURN (addr, ACE_HTTP_Addr (), 0);
96 else if (ACE_OS::strncasecmp (ftp, url, ftp_size) == 0)
97 ACE_NEW_RETURN (addr, ACE_FTP_Addr (), 0);
98 else if (ACE_OS::strncasecmp (mailto, url, mailto_size) == 0)
99 ACE_NEW_RETURN (addr, ACE_Mailto_Addr (), 0);
100 else
101 ACE_NEW_RETURN (addr, ACE_URL_Addr (), 0);
103 if (addr->string_to_addr (url) != 0)
105 delete addr;
106 addr = 0;
108 return addr;
112 ACE_URL_Addr::known_scheme (const ACE_TCHAR *url)
114 if (ACE_OS::strncasecmp (http, url, http_size) == 0)
115 return 1;
116 else if (ACE_OS::strncasecmp (ftp, url, ftp_size) == 0)
117 return 1;
118 else if (ACE_OS::strncasecmp (mailto, url, mailto_size) == 0)
119 return 1;
120 else if (ACE_OS::strncasecmp (file, url, file_size) == 0)
121 return 1;
122 else if (ACE_OS::strncasecmp (afs, url, afs_size) == 0)
123 return 1;
124 else if (ACE_OS::strncasecmp (news, url, news_size) == 0)
125 return 1;
126 else if (ACE_OS::strncasecmp (nntp, url, nntp_size) == 0)
127 return 1;
128 else if (ACE_OS::strncasecmp (cid, url, cid_size) == 0)
129 return 1;
130 else if (ACE_OS::strncasecmp (mid, url, mid_size) == 0)
131 return 1;
132 else if (ACE_OS::strncasecmp (wais, url, wais_size) == 0)
133 return 1;
134 else if (ACE_OS::strncasecmp (prospero, url, prospero_size) == 0)
135 return 1;
136 else if (ACE_OS::strncasecmp (telnet, url, telnet_size) == 0)
137 return 1;
138 else if (ACE_OS::strncasecmp (rlogin, url, rlogin_size) == 0)
139 return 1;
140 else if (ACE_OS::strncasecmp (tn3270, url, tn3270_size) == 0)
141 return 1;
142 else if (ACE_OS::strncasecmp (gopher, url, gopher_size) == 0)
143 return 1;
145 return 0;
148 // ****************************************************************
150 ACE_URL_Addr_Visitor::~ACE_URL_Addr_Visitor ()
155 ACE_URL_Addr_Visitor::visit (ACE_URL_Addr*)
157 return 0;
161 ACE_URL_Addr_Visitor::visit (ACE_HTTP_Addr*)
163 return 0;
167 ACE_URL_Addr_Visitor::visit (ACE_FTP_Addr*)
169 return 0;
173 ACE_URL_Addr_Visitor::visit (ACE_Mailto_Addr*)
175 return 0;
178 // ****************************************************************
180 ACE_HTTP_Addr::ACE_HTTP_Addr ()
181 : hostname_ (0),
182 port_number_ (0),
183 path_ (0),
184 query_ (0)
188 ACE_HTTP_Addr::ACE_HTTP_Addr (const ACE_TCHAR *host_name,
189 const ACE_TCHAR *path,
190 const ACE_TCHAR *query,
191 u_short port)
192 : hostname_ (0),
193 port_number_ (0),
194 path_ (0),
195 query_ (0)
197 this->set (host_name, path, query, port);
200 ACE_HTTP_Addr::ACE_HTTP_Addr (const ACE_HTTP_Addr &addr)
201 : ACE_URL_Addr (),
202 hostname_ (0),
203 port_number_ (0),
204 path_ (0),
205 query_ (0)
207 this->set (addr);
210 ACE_HTTP_Addr::~ACE_HTTP_Addr ()
212 this->clear ();
213 this->hostname_ = 0;
214 this->path_ = 0;
215 this->query_ = 0;
219 ACE_HTTP_Addr::set (const ACE_TCHAR *host_name,
220 const ACE_TCHAR *path,
221 const ACE_TCHAR *query,
222 u_short port)
224 if (host_name == 0 || path == 0)
225 return -1;
227 this->clear ();
228 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (host_name), -1);
229 this->port_number_ = port;
230 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (path), -1);
231 if (query != 0)
232 ACE_ALLOCATOR_RETURN (this->query_, ACE_OS::strdup (query), -1);
233 else
234 this->query_ = 0;
236 size_t size = this->url_size (1);
238 ACE_TCHAR *buffer;
239 ACE_ALLOCATOR_RETURN (buffer,
240 reinterpret_cast<ACE_TCHAR *> (ACE_OS::malloc (size)),
241 -1);
242 if (this->addr_to_string (buffer, size, 1) == -1)
243 return -1;
244 this->set_url (buffer);
245 return 0;
249 ACE_HTTP_Addr::set (const ACE_HTTP_Addr &addr)
251 if (this->ACE_URL_Addr::set (addr) != 0)
252 return -1;
253 this->clear ();
254 if (addr.hostname_ != 0)
255 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (addr.hostname_), -1);
256 else
257 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (ACE_TEXT ("")), -1);
258 if (addr.path_ != 0)
259 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (addr.path_), -1);
260 else
261 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (ACE_TEXT ("")), -1);
262 this->port_number_ = addr.port_number_;
263 if (addr.query_ != 0)
264 ACE_ALLOCATOR_RETURN (this->query_, ACE_OS::strdup (addr.query_), -1);
265 else
266 this->query_ = 0;
267 return 0;
270 void
271 ACE_HTTP_Addr::clear ()
273 if (this->hostname_ != 0)
274 ACE_OS::free (this->hostname_);
275 if (this->path_ != 0)
276 ACE_OS::free (this->path_);
277 if (this->query_ != 0)
278 ACE_OS::free (this->query_);
281 size_t
282 ACE_HTTP_Addr::url_size (int flags) const
284 // Notice that we cannot hard-code the value because the size in
285 // wchar's may be different.
286 size_t size =
287 + sizeof (ACE_TEXT ("http://"))
288 + sizeof (ACE_TEXT ("/:?")); // separators
290 size_t chars =
291 + (this->path_?ACE_OS::strlen (this->path_):0)
292 + (this->query_?ACE_OS::strlen (this->query_):0);
295 if (flags == 0)
297 size += sizeof (ACE_TEXT("255.255.255.255"));
299 else
301 chars += ACE_OS::strlen (this->hostname_);
304 if (this->port_number_ != ACE_DEFAULT_HTTP_PORT)
306 size += sizeof (ACE_TEXT(":65335"));
309 size += chars * sizeof(ACE_TCHAR);
311 return size;
314 inline int
315 path_copy (const ACE_TCHAR *begin,
316 const ACE_TCHAR * /* end */,
317 ACE_TCHAR *& target,
318 const ACE_TCHAR *src)
320 // Copy one character at a time, if we find a /../ we go back to the
321 // previous '/'
322 for (; *src != 0; ++src)
324 ACE_TCHAR c = *src;
326 switch (c)
328 case '/':
329 if (src[1] == '.' && src[2] == '.' && src[3] == '/')
331 while (target != begin && *(--target) != '/')
333 // No action.
336 src += 3;
338 else if (src[1] == '.' && src[2] == '/')
340 src += 2;
342 else
344 *target = c;
345 ++target;
347 break;
348 default:
349 *target = c;
350 ++target;
353 return 0;
356 ACE_URL_Addr*
357 ACE_HTTP_Addr::create_relative_address (const ACE_TCHAR *url) const
359 if (ACE_URL_Addr::known_scheme (url))
360 return ACE_URL_Addr::create_address (url);
362 ACE_HTTP_Addr* addr = 0;
363 if (url[0] == '/')
365 ACE_NEW_RETURN (addr, ACE_HTTP_Addr (this->get_hostname (),
366 url + 1,
368 this->get_port_number ()),
371 else
373 const ACE_TCHAR *path = this->get_path ();
374 ACE_TCHAR *buf;
375 size_t n = ACE_OS::strlen (url)
376 + ACE_OS::strlen (path)
377 + 2;
378 ACE_NEW_RETURN (buf,
379 ACE_TCHAR [n],
382 // We copy the contens of <path> into <buf>; but simplifying the
383 // path, to avoid infinite loop like:
384 // "foo/../foo/../foo/../foo/../foo/index.html"
386 ACE_TCHAR *target = buf;
388 // Copy the path
389 path_copy (buf, buf + n, target, path);
391 if (url[0] == '#')
393 // Remove any # from the path
394 ACE_TCHAR *p = target;
396 while (p != buf && *(--p) != '#')
398 // No action.
401 if (p != buf)
402 target = p;
404 else
406 // Go back to the last / to remove the basename.
407 while (target != buf && *(--target) != '/')
409 // No action.
412 // Go back if we begin with '../'
413 while ((url[0] == '.' && url[1] == '.' && url[2] == '/')
414 || (url[0] == '.' && url[1] == '/'))
416 if (url[1] == '.')
418 // A ../ go back
419 while (target != buf && *(--target) != '/')
421 // No action.
424 url += 3;
426 else
428 // A ./ remove
429 url += 2;
433 *target = '/'; ++target;
435 // Copy the url
436 path_copy (buf, buf + n, target, url);
437 // null terminate.
438 *target = 0;
439 ACE_NEW_RETURN (addr, ACE_HTTP_Addr (this->get_hostname (),
440 buf,
442 this->get_port_number ()),
444 delete[] buf;
447 return addr;
451 ACE_HTTP_Addr::string_to_addr (const ACE_TCHAR *address)
453 if (address == 0)
454 return -1;
456 if (ACE_OS::strncasecmp (http, address, http_size) != 0)
457 return -1;
459 this->clear ();
460 this->hostname_ = 0;
461 this->path_ = 0;
462 this->query_ = 0;
464 // Save the original URL....
465 if (this->ACE_URL_Addr::string_to_addr (address) != 0)
466 return -1;
468 const ACE_TCHAR *string = address;
469 string += http_size;
470 string += 2; // == strlen ("//");
472 // Make a copy of the string to manipulate it.
473 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (string), -1);
475 ACE_TCHAR *path_start = ACE_OS::strchr (this->hostname_, '/');
476 if (path_start != 0)
478 // terminate the host:port substring
479 path_start[0] = '\0';
480 path_start++;
481 ACE_TCHAR *query_start = ACE_OS::strchr (path_start, '?');
482 if (query_start != 0)
484 query_start[0] = '\0';
485 query_start++;
486 ACE_ALLOCATOR_RETURN (this->query_,
487 ACE_OS::strdup (query_start),
488 -1);
490 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (path_start), -1);
493 // By now t is null terminated at the start of the path, find the
494 // port (if present).
495 ACE_TCHAR *port_start = ACE_OS::strchr(this->hostname_, ':');
496 this->port_number_ = ACE_DEFAULT_HTTP_PORT;
497 if (port_start != 0)
499 // terminate the ipaddr.
500 port_start[0] = '\0';
501 port_start++;
502 this->port_number_ = ACE_OS::atoi (port_start);
505 return 0;
509 ACE_HTTP_Addr::addr_to_string (ACE_TCHAR *buffer,
510 size_t size,
511 int flags) const
513 if (size < this->url_size (flags))
514 return -1;
516 if (this->hostname_ == 0)
517 return -1;
519 size_t n = ACE_OS::sprintf (buffer,
520 ACE_TEXT ("http://"));
521 if (flags == 0)
523 ACE_INET_Addr inet = this->get_inet_address ();
524 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("%") ACE_TEXT_PRIs, inet.get_host_addr ());
526 else
528 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("%") ACE_TEXT_PRIs, this->hostname_);
531 if (this->port_number_ != ACE_DEFAULT_HTTP_PORT)
533 n += ACE_OS::sprintf (buffer + n, ACE_TEXT (":%d"), this->port_number_);
535 if (this->path_ != 0)
537 n += ACE_OS::sprintf (buffer + n,
538 ACE_TEXT ("/%") ACE_TEXT_PRIs,
539 this->path_);
541 if (this->query_ != 0)
543 n += ACE_OS::sprintf (buffer + n,
544 ACE_TEXT ("?%") ACE_TEXT_PRIs,
545 this->query_);
547 return 0;
551 ACE_HTTP_Addr::accept (ACE_URL_Addr_Visitor *visitor)
553 return visitor->visit (this);
556 // ****************************************************************
558 ACE_FTP_Addr::ACE_FTP_Addr ()
559 : user_ (0),
560 password_ (0),
561 hostname_ (0),
562 path_ (0)
566 ACE_FTP_Addr::ACE_FTP_Addr (const ACE_TCHAR *host_name,
567 const ACE_TCHAR *path,
568 const ACE_TCHAR *user,
569 const ACE_TCHAR *password)
570 : user_ (0),
571 password_ (0),
572 hostname_ (0),
573 path_ (0)
575 this->set (host_name, path, user, password);
578 ACE_FTP_Addr::ACE_FTP_Addr (const ACE_FTP_Addr& addr)
579 : ACE_URL_Addr (),
580 user_ (0),
581 password_ (0),
582 hostname_ (0),
583 path_ (0)
585 this->set (addr);
588 ACE_FTP_Addr::~ACE_FTP_Addr ()
590 this->clear ();
594 ACE_FTP_Addr::set (const ACE_TCHAR *host_name,
595 const ACE_TCHAR *path,
596 const ACE_TCHAR *user,
597 const ACE_TCHAR *password)
599 if (host_name == 0 || path == 0)
600 return -1;
601 this->clear ();
602 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (host_name), -1);
603 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (path), -1);
604 if (user != 0)
605 ACE_ALLOCATOR_RETURN (this->user_, ACE_OS::strdup (user), -1);
606 else
607 this->user_ = 0;
608 if (this->password_ != 0)
609 ACE_ALLOCATOR_RETURN (this->password_, ACE_OS::strdup (password), -1);
610 else
611 this->password_ = 0;
613 size_t size = this->url_size (1);
615 ACE_TCHAR *buffer;
616 ACE_ALLOCATOR_RETURN (buffer,
617 reinterpret_cast<ACE_TCHAR *> (ACE_OS::malloc (size)),
618 -1);
619 if (this->addr_to_string (buffer, size, 1) == -1)
620 return -1;
621 this->set_url (buffer);
622 return 0;
626 ACE_FTP_Addr::set (const ACE_FTP_Addr& addr)
628 if (this->ACE_URL_Addr::set (addr) != 0)
629 return -1;
630 this->clear ();
631 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (addr.hostname_), -1);
632 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (addr.path_), -1);
633 if (addr.user_ != 0)
634 ACE_ALLOCATOR_RETURN (this->user_, ACE_OS::strdup (addr.user_), -1);
635 else
636 this->user_ = 0;
637 if (addr.password_ != 0)
638 ACE_ALLOCATOR_RETURN (this->password_, ACE_OS::strdup (addr.password_), -1);
639 else
640 this->password_ = 0;
641 return 0;
644 void
645 ACE_FTP_Addr::clear ()
647 if (this->hostname_ != 0)
648 ACE_OS::free (this->hostname_);
649 if (this->path_ != 0)
650 ACE_OS::free (this->path_);
651 if (this->user_ != 0)
652 ACE_OS::free (this->user_);
653 if (this->password_ != 0)
654 ACE_OS::free (this->password_);
657 size_t
658 ACE_FTP_Addr::url_size (int flags) const
660 // Notice that we cannot hard-code the value because the size in
661 // wchar's may be different.
662 size_t size =
663 + sizeof (ACE_TEXT ("ftp://"))
664 + sizeof (ACE_TEXT ("@:/")); // separators
666 size_t chars =
667 + (this->user_?ACE_OS::strlen (this->path_):0)
668 + (this->password_?ACE_OS::strlen (this->password_):0)
669 + (this->path_?ACE_OS::strlen (this->path_):0);
671 if (flags == 0)
673 size += sizeof (ACE_TEXT("255.255.255.255"));
675 else
677 chars += ACE_OS::strlen (this->hostname_);
680 size += chars * sizeof(ACE_TCHAR);
681 return size;
685 ACE_FTP_Addr::addr_to_string (ACE_TCHAR *buffer,
686 size_t size,
687 int flags) const
689 if (size < this->url_size (flags))
690 return -1;
692 size_t n = ACE_OS::sprintf (buffer,
693 ACE_TEXT ("ftp://"));
695 if (this->user_ != 0)
697 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("%") ACE_TEXT_PRIs, this->user_);
699 if (this->password_ != 0)
701 n += ACE_OS::sprintf (buffer + n,
702 ACE_TEXT (":%") ACE_TEXT_PRIs,
703 this->password_);
706 if (this->user_ != 0)
708 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("@"));
711 if (flags == 0)
713 ACE_INET_Addr inet = this->get_inet_address ();
714 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("%") ACE_TEXT_PRIs, inet.get_host_addr ());
716 else
718 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("%") ACE_TEXT_PRIs, this->hostname_);
720 if (this->path_ != 0)
722 n += ACE_OS::sprintf (buffer + n,
723 ACE_TEXT ("/%") ACE_TEXT_PRIs,
724 this->path_);
726 return 0;
730 ACE_FTP_Addr::string_to_addr (const ACE_TCHAR *address)
732 if (address == 0)
733 return -1;
734 if (ACE_OS::strncasecmp (ftp, address, ftp_size) != 0)
735 return -1;
737 this->clear ();
738 this->hostname_ = 0;
739 this->user_ = 0;
740 this->password_ = 0;
741 this->path_ = 0;
743 // Save the original URL....
744 this->ACE_URL_Addr::string_to_addr (address);
746 const ACE_TCHAR *string = address;
747 string += ftp_size;
748 string += 2; // == strlen ("//");
750 // Make a copy of the string to manipulate it.
751 ACE_TCHAR *t;
752 ACE_ALLOCATOR_RETURN (t, ACE_OS::strdup (string), -1);
754 ACE_TCHAR *path_start = ACE_OS::strchr (t, '/');
755 if (path_start != 0)
757 // terminate the host:port substring
758 path_start[0] = '\0';
759 path_start++;
760 ACE_ALLOCATOR_RETURN (this->path_, ACE_OS::strdup (path_start), -1);
763 ACE_TCHAR *host_start = ACE_OS::strchr (t, '@');
764 if (host_start != 0)
766 host_start[0] = '\0';
767 host_start++;
768 ACE_ALLOCATOR_RETURN (this->hostname_,
769 ACE_OS::strdup (host_start),
770 -1);
771 ACE_TCHAR *pass_start = ACE_OS::strchr (t, ':');
772 if (pass_start != 0)
774 pass_start[0] = '\0';
775 pass_start++;
776 ACE_ALLOCATOR_RETURN (this->password_,
777 ACE_OS::strdup (pass_start),
778 -1);
780 this->user_ = t;
782 else
784 this->hostname_ = t;
787 return 0;
791 ACE_FTP_Addr::accept (ACE_URL_Addr_Visitor* visitor)
793 return visitor->visit (this);
796 // ****************************************************************
798 ACE_Mailto_Addr::ACE_Mailto_Addr ()
799 : user_ (0),
800 hostname_ (0),
801 headers_ (0)
805 ACE_Mailto_Addr::ACE_Mailto_Addr (const ACE_TCHAR *user,
806 const ACE_TCHAR *hostname,
807 const ACE_TCHAR *headers)
808 : user_ (0),
809 hostname_ (0),
810 headers_ (0)
812 this->set (user, hostname, headers);
815 ACE_Mailto_Addr::ACE_Mailto_Addr (const ACE_Mailto_Addr &addr)
816 : ACE_URL_Addr (addr),
817 user_ (0),
818 hostname_ (0),
819 headers_ (0)
821 this->set (addr);
824 ACE_Mailto_Addr::~ACE_Mailto_Addr ()
826 this->clear ();
830 ACE_Mailto_Addr::set (const ACE_TCHAR *user,
831 const ACE_TCHAR *hostname,
832 const ACE_TCHAR *headers)
834 if (user == 0 || hostname == 0)
835 return -1;
836 this->clear ();
837 ACE_ALLOCATOR_RETURN (this->user_, ACE_OS::strdup (user), -1);
838 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (hostname), -1);
839 if (headers != 0)
840 ACE_ALLOCATOR_RETURN (this->headers_, ACE_OS::strdup (headers), -1);
841 else
842 this->headers_ = 0;
843 size_t size = this->url_size (1);
844 ACE_TCHAR *buffer;
845 ACE_ALLOCATOR_RETURN (buffer,
846 reinterpret_cast<ACE_TCHAR *> (ACE_OS::malloc (size)),
847 -1);
848 if (this->addr_to_string (buffer, size, 1) == -1)
849 return -1;
850 this->set_url (buffer);
851 return 0;
855 ACE_Mailto_Addr::set (const ACE_Mailto_Addr &addr)
857 if (this->ACE_URL_Addr::set (addr) != 0)
858 return -1;
859 this->clear ();
860 ACE_ALLOCATOR_RETURN (this->user_, ACE_OS::strdup (addr.user_), -1);
861 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (addr.hostname_), -1);
862 if (addr.headers_ != 0)
863 ACE_ALLOCATOR_RETURN (this->headers_, ACE_OS::strdup (addr.headers_), -1);
864 else
865 this->headers_ = 0;
866 return 0;
869 void
870 ACE_Mailto_Addr::clear ()
872 if (this->user_ != 0)
873 ACE_OS::free (this->user_);
874 if (this->hostname_ != 0)
875 ACE_OS::free (this->hostname_);
876 if (this->headers_ != 0)
877 ACE_OS::free (this->headers_);
880 size_t
881 ACE_Mailto_Addr::url_size (int) const
883 // Notice that we cannot hard-code the value because the size in
884 // wchar's may be different.
885 size_t size = sizeof (ACE_TEXT ("mailto:"))
886 + sizeof (ACE_TEXT ("@?")); // separators
888 size_t chars =
889 + (this->user_?ACE_OS::strlen (this->user_):0)
890 + (this->hostname_?ACE_OS::strlen (this->hostname_):0)
891 + (this->headers_?ACE_OS::strlen (this->headers_):0);
892 size += chars * sizeof (ACE_TCHAR);
894 return size;
898 ACE_Mailto_Addr::addr_to_string (ACE_TCHAR *buffer,
899 size_t size,
900 int flags) const
902 if (size < this->url_size (flags))
903 return -1;
904 if (this->user_ == 0 || this->hostname_ == 0)
905 return -1;
907 size_t n = ACE_OS::sprintf (buffer,
908 ACE_TEXT ("mailto:%") ACE_TEXT_PRIs
909 ACE_TEXT ("@%") ACE_TEXT_PRIs,
910 this->user_, this->hostname_);
911 if (this->headers_ != 0)
913 n += ACE_OS::sprintf (buffer + n, ACE_TEXT ("?%") ACE_TEXT_PRIs,
914 this->headers_);
917 return 0;
921 ACE_Mailto_Addr::string_to_addr (const ACE_TCHAR *address)
923 if (ACE_OS::strncasecmp (mailto, address, mailto_size) != 0)
924 return -1;
926 this->clear ();
927 this->user_ = 0;
928 this->hostname_ = 0;
929 this->headers_ = 0;
931 // Save the original URL....
932 if (this->ACE_URL_Addr::string_to_addr (address) != 0)
933 return -1;
935 const ACE_TCHAR *string = address;
936 string += mailto_size;
938 // Make a copy of the string to manipulate it.
939 ACE_TCHAR *t;
940 ACE_ALLOCATOR_RETURN (t, ACE_OS::strdup (string), -1);
942 ACE_TCHAR *host_start = ACE_OS::strchr (t, '@');
943 if (host_start != 0)
945 // terminate the host:port substring
946 host_start[0] = '\0';
947 host_start++;
948 ACE_TCHAR *headers_start = ACE_OS::strchr (host_start, '?');
949 if (headers_start != 0)
951 headers_start[0] = '\0';
952 headers_start++;
953 ACE_ALLOCATOR_RETURN (this->headers_,
954 ACE_OS::strdup (headers_start),
955 -1);
957 ACE_ALLOCATOR_RETURN (this->hostname_, ACE_OS::strdup (host_start), -1);
959 else
961 ACE_OS::free (t);
962 return -1;
964 this->user_ = t;
966 return 0;
970 ACE_Mailto_Addr::accept (ACE_URL_Addr_Visitor* visitor)
972 return visitor->visit (this);