fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / Contrib / WebInterface / OSGWebInterface.cpp
blob13bcf50df8e3d1465f1d5c6eee8e3585c3d19104
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #include "OSGConfig.h"
40 #include "OSGFieldContainerFields.h"
41 #include "OSGNodeCore.h"
42 #include "OSGLog.h"
43 #include "OSGNameAttachment.h"
44 #include "OSGRootGroup.h"
46 #include "OSGWebInterface.h"
48 OSG_USING_NAMESPACE
50 /*! \class osg::WebInterface
52 The WebInterface class provides a simple access to all
53 FieldContainers in a running OpenSG application. If
54 handleRequests() is called in each render loop, it is
55 possible to connect the interface with a standard web
56 browser http://hostname:8888. In glut applications the
57 idle functions could be used. It is possible to add
58 new features to the interface by subclassing and adding
59 new handlers.
63 WebInterface::CreateFunc WebInterface::_createFunc = NULL;
65 WebInterface::ObjTransitPtr WebInterface::create(UInt32 port)
67 if(_createFunc)
69 return _createFunc(port);
71 else
73 return WebInterfaceTransitPtr(new WebInterface(port));
77 void WebInterface::setCreatorFunc(CreateFunc createFunc)
79 _createFunc = createFunc;
82 /*-------------------------------------------------------------------------*/
83 /* Constructors */
85 WebInterface::WebInterface(void) :
86 Inherited ( ),
87 _socket ( ),
88 _accepted ( ),
89 _body ( ),
90 _handler ( ),
91 _root (NULL ),
92 _systemContainer(NULL ),
93 _header (getDefaultHeader()),
94 _footer ( ),
95 _clist (NULL )
99 /*! Cunstruct a WebInterface for the given port. If the port
100 is used, try to bind to the following port number.
102 WebInterface::WebInterface(UInt32 port) :
103 Inherited ( ),
104 _socket ( ),
105 _accepted ( ),
106 _body ( ),
107 _handler ( ),
108 _root (NULL ),
109 _systemContainer(NULL ),
110 _header (getDefaultHeader()),
111 _footer ( ),
112 _clist (NULL )
114 bool bound=false;
116 _socket.open();
117 _socket.setReusePort(true);
123 _socket.bind(SocketAddress(SocketAddress::ANY,port));
124 _socket.listen();
126 bound = true;
128 catch(SocketException &)
130 port++;
133 while(!bound);
135 FLOG(("WebInterface bound to port:%d\n",port));
137 // register bas handlers
138 addHandler("/" , &WebInterface::rootHandler);
139 addHandler("/changelist", &WebInterface::changelistHandler);
140 addHandler("/fcview" , &WebInterface::fcViewHandler);
141 addHandler("/fcedit" , &WebInterface::fcEditHandler);
142 addHandler("/treeview" , &WebInterface::treeViewHandler);
145 /*-------------------------------------------------------------------------*/
146 /* Destructor */
148 /*! Destructor
151 WebInterface::~WebInterface(void)
153 _socket.close();
156 /*-------------------------------------------------------------------------*/
157 /* request handling */
159 /*! Handle all incoming http requests. Return, if no request is
160 pending
163 void WebInterface::handleRequests(void)
165 std::string path,url;
166 ParameterT param;
167 HandlerT::iterator hI;
169 while(checkRequest(url))
171 decodeUrl(url,path,param);
172 // write http header
174 _body.str("");
175 _body <<
176 "HTTP/1.1 200 OK\r\n"
177 "Connection: close\r\n"
178 "Server: OpenSGMicroWebInterface\r\n"
179 "Expires: 0\r\n";
181 // find handler
182 hI = _handler.find(path);
184 if(hI != _handler.end())
186 (this->*hI->second)(_body,path.c_str(),param);
188 else
190 _body << "Content-Type: text/html\r\n"
191 "\r\n"
192 "<html>Invalid path</html>";
195 _body.flush();
196 _accepted.setDelay(false);
198 // finish request
199 _accepted.send(_body.str().c_str(), _body.str().length());
201 // close connection
202 _accepted.close();
206 /*! Flush the data that's alrady in the stream to allow incremental creation
207 and updates on slow operaitons
210 void WebInterface::flush(void)
212 _body.flush();
213 _accepted.setDelay(false);
215 // finish request
216 _accepted.send(_body.str().c_str(), _body.str().length());
217 _body.str("");
220 /*! Suspend processing until a http request is pending for the
221 given duration in seconds. If duration is < 0. waitRequest
222 will wait vor ever
225 bool WebInterface::waitRequest(double duration)
229 if(!_socket.waitReadable(duration))
230 return false;
232 catch(SocketException &)
234 return false;
237 return true;
240 /*-------------------------------------------------------------------------*/
241 /* set */
243 /*! Set the ChangeList. By default the ChangeList of the current thread is
244 used, but it can be overriden by this function.
247 void WebInterface::setChangeList(ChangeList *clist)
249 _clist = clist;
252 /*! Set the scenegraph root node.
255 void WebInterface::setSystemContainer(FieldContainer *system)
257 _systemContainer = system;
260 /*! Set the scenegraph root node.
262 void WebInterface::setRoot(Node *root)
264 _root = root;
267 /*! Set the html header.
269 void WebInterface::setHeader(const std::string &header)
271 _header = header;
274 /*! Set the html footer.
276 void WebInterface::setFooter(const std::string &footer)
278 _footer = footer;
281 /*-------------------------------------------------------------------------*/
282 /* get */
285 /*! Get the scenegraph root node.
288 FieldContainer *WebInterface::getSystemContainer(void)
290 return _systemContainer;
293 /*! Get the scenegraph root node.
296 Node *WebInterface::getRoot(void)
298 return _root;
301 /*! Get the html header.
304 const std::string &WebInterface::getHeader(void)
306 return _header;
309 /*! Get the html footer.
312 const std::string &WebInterface::getFooter(void)
314 return _footer;
317 /*-------------------------------------------------------------------------*/
318 /* handler management */
320 /*! Add a new page handler
322 void WebInterface::addHandler(const Char8 *path, MethodT method)
324 // This is a workaround for gcc 3.1 on OS X
326 HandlerT::value_type newEntry(path, method);
328 std::pair<HandlerT::iterator, bool> retVal;
330 retVal = _handler.insert(newEntry);
332 if(retVal.second == false)
333 retVal.first->second = method;
335 // _handler[IDString(path)] = method;
338 /*-------------------------------------------------------------------------*/
339 /* url encoding/decoding */
341 /*! Encode the given path and params into a valid http url.
344 std::string WebInterface::encodeUrl(const std::string &path,
345 const ParameterT &param)
347 std::string result=path;
348 ParameterT::const_iterator pI;
349 unsigned int c;
350 char ch;
352 const char *hex="0123456789abcdef";
354 if(param.size())
355 result += "?";
357 for(pI = param.begin() ; pI != param.end() ; ++pI)
359 if(pI != param.begin())
360 result += '&';
362 result += pI->first.c_str();
364 if(!pI->second.empty())
365 result += '=';
367 for(c = 0 ; c < UInt32(pI->second.length()) ; ++c)
369 ch = pI->second.c_str()[c];
371 switch(ch)
373 case ' ':
374 result += '+';
375 break;
376 case '+':
377 case ';':
378 case '/':
379 case '?':
380 case ':':
381 case '@':
382 case '&':
383 case '=':
384 result += '%';
385 result += hex[ch / 16];
386 result += hex[ch & 15];
387 break;
388 default:
389 result += ch;
394 return result;
397 /*! strip and decode parameter values from a given URL. Parameter,
398 value paires are stored in a string map.
401 void WebInterface::decodeUrl(const std::string &url,
402 std::string &path,
403 ParameterT &param)
405 std::string::const_iterator sI=url.begin();
406 std::string name,value;
407 char bu[2];
408 int c;
410 path = "";
411 param.clear();
413 while(sI !=url.end() && *sI != ' ' && *sI != '?')
414 path += *(sI++);
416 if(sI !=url.end() && *sI == '?')
420 name = value = "";
421 // read name
423 while(++sI != url.end() &&
424 *sI != ' ' &&
425 *sI != '=' &&
426 *sI != '&' )
428 name += *sI;
431 if(sI != url.end() && *sI == '=')
433 // read value
434 while(++sI != url.end() && *sI != ' ' && *sI != '&')
436 switch(*sI)
438 case '+': value += ' ';
439 break;
441 case '%':
442 for(c = 0 ; c < 2 ; ++c)
444 bu[c] = *(++sI);
446 if(bu[c] >= 'A')
448 bu[c] = bu[c] - 'A' + 10;
450 else
452 if(bu[c] >= 'a')
453 bu[c] = bu[c] - 'a' + 10;
454 else
455 bu[c] -= '0';
459 value += char(bu[0]*16+bu[1]);
460 break;
462 default:
463 value += *sI;
468 setParam(param,name.c_str(),value.c_str());
470 } while(sI != url.end() && *sI == '&');
474 /*-------------------------------------------------------------------------*/
475 /* helper */
477 /*! Helper function. Create a link to a node view html page.
480 std::string WebInterface::createFCViewReference(FieldContainer *fcPtr,
481 UInt32 fcId)
483 std::stringstream result;
485 if(fcPtr == NULL)
487 if(fcId)
488 result << "Unknown(" << fcId << ")";
489 else
490 result << "NullFC";
492 else
494 result << "<a href =\"fcview?id="
495 << fcPtr->getId()
496 << "\">"
497 << fcPtr->getType().getName()
498 << " ("
499 << fcPtr->getId()
500 << ")"
501 << "</a>";
504 return result.str();
507 /*! get parameter. If the parameter is not set, NULL
508 is returned.
511 const char *WebInterface::getParam(ParameterT &param, const char *name)
513 ParameterT::iterator pI = param.find(std::string(name));
515 if(pI == param.end())
516 return NULL;
517 else
518 return pI->second.c_str();
521 /*! set parameter to the given value. If value is NULL, the
522 parameter is removed.
524 void WebInterface::setParam( ParameterT &param,
525 const char *name,
526 const char *value)
528 if(!value)
529 param.erase(std::string(name));
530 else
531 param[std::string(name)] = std::string(value);
534 /*! Handle pending http requests. The requested url is return in
535 url. If no request is pending, false is returned.
537 bool WebInterface::checkRequest(std::string &url)
539 std::string name,value;
540 char bu[4];
541 char ch;
543 url = "";
547 if(!_socket.waitReadable(0))
548 return false;
550 catch(SocketException &)
552 return false;
555 _accepted = _socket.accept();
557 if(_accepted.recv(bu,4) && strncmp(bu,"GET ",4) == 0)
559 while(_accepted.recv(&ch, 1) && ch != ' ')
560 url += ch;
564 while(_accepted.recv(&ch, 1) && ch != '\n');
566 while(_accepted.recv(&ch, 1) && ch != '\r');
568 _accepted.recv(&ch, 1);
570 if(url.empty())
571 return false;
572 else
573 return true;
576 /*! Traversal function for the treeViewHandler
578 void WebInterface::treeViewNode(std::ostream &os,
579 Node *node,
580 ParameterT &param)
582 ParameterT::const_iterator pI;
583 char idstr[32];
584 std::string folder;
586 if(node == NULL)
588 os << "<li>NullFC</li>\n";
589 return;
592 sprintf(idstr,"%u",node->getId());
594 if(param.count(std::string(idstr)))
596 setParam(param,"close",idstr);
597 folder = encodeUrl("treeview",param);
598 setParam(param,"close",NULL);
599 os << "<li><a href=\"" << folder << "\">&nbsp - &nbsp</a>";
601 else
603 setParam(param,"open",idstr);
604 folder = encodeUrl("treeview",param);
605 setParam(param,"open",NULL);
606 os << "<li><a href=\"" << folder << "\">&nbsp + &nbsp</a>";
609 os << "&nbsp &nbsp &nbsp "
610 << "<b>" << getNodeName(node) << "</b>&nbsp &nbsp &nbsp "
611 << createFCViewReference(node);
613 if(node->getCore() != NULL)
615 os << "&nbsp &nbsp &nbsp Core: "
616 << createFCViewReference(node->getCore());
618 os << "</li>";
620 if(param.count(std::string(idstr)))
622 os << "<ul>\n";
623 Node::MFChildrenType::const_iterator nI =
624 node->getMFChildren()->begin();
626 for(; nI != node->getMFChildren()->end(); ++nI)
628 treeViewNode(os,*nI,param);
631 RootGroup *pRG = dynamic_cast<RootGroup *>(node->getCore());
633 if(pRG != NULL)
635 treeViewNode(os, pRG->getRoot(), param);
638 os << "</ul>\n";
642 /*-------------------------------------------------------------------------*/
643 /* web page handler */
645 /*! main page
647 void WebInterface::rootHandler( std::ostream &os,
648 const char *,
649 ParameterT & )
651 os << "Content-Type: text/html\r\n"
652 "\r\n"
653 "<html>"
654 << _header;
656 os << "<h1>OpenSG Web Interface</h1>"
657 << "<ui>"
658 << "<li><a href=\"changelist\">ChangeList</a>"
659 << "<li><a href=\"treeview\">SceneGraph</a>"
660 << "<li><b>" << getNodeName(_systemContainer) << "</b>&nbsp &nbsp &nbsp "
661 << createFCViewReference(_systemContainer)
662 << "</ui>";
663 os << _footer << "</html>";
666 /*! View the current changelist
668 void WebInterface::changelistHandler(std::ostream &os,
669 const char *,
670 ParameterT &)
672 #if 0
673 ChangeList::idrefd_const_iterator createdI;
674 ChangeList::changed_const_iterator changedI;
675 ChangeList::idrefd_const_iterator destroyedI;
676 FieldContainerPtr fcPtr;
677 ChangeList *changeList;
678 std::string type,mask;
679 int col=0;
680 const int createdCols=6;
681 const int changedCols=3;
682 const int destroyedCols=6;
684 if(_clist == NULL)
686 changeList=OSG::Thread::getCurrentChangeList();
688 else
690 changeList = _clist;
693 os << "Content-Type: text/html\r\n"
694 "\r\n"
695 "<html>" << _header
696 << "<h1>ChangeList</h1>";
698 // created
699 os << "<h2>Created</h2>"
700 << "<table><tr>";
701 for(col = 0 ; col < createdCols ; ++col)
702 os << "<th>FieldContainer</th>";
703 os << "</tr>\n";
704 for(col = 0,createdI = changeList->beginCreated();
705 createdI != changeList->endCreated(); createdI++)
707 fcPtr = FieldContainerFactory::the()->getContainer(*createdI);
708 if(!col)
709 os << "<tr>";
710 os << "<td>" << createFCViewReference(fcPtr) << "</td>";
711 col = (col+1) % createdCols;
712 if(!col)
713 os << "</tr>\n";
715 while(col && col++ < createdCols)
716 os << "<td>&nbsp;</td>";
717 os << "</tr>\n</table>\n";
719 // Changed
720 os << "<h2>Changed</h2>"
721 << "<table><tr>";
722 for(col = 0 ; col < changedCols ; ++col)
723 os << "<th>FieldContainer</th><th>Change Mask</th>";
724 os << "</tr>\n";
725 for(col = 0,changedI = changeList->beginChanged();
726 changedI != changeList->endChanged();
727 changedI++)
729 fcPtr = FieldContainerFactory::the()->getContainer(changedI->first);
730 mask = "Unknown";
731 if(fcPtr != NullFC)
733 if(changedI->second == FieldBits::AllFields)
734 mask = "AllFields";
735 else
737 mask = "";
738 for(unsigned int i=0;i<fcPtr->getType().getNumFieldDescs();i++)
740 FieldDescription *desc=fcPtr->getType().getFieldDescription(i+1);
741 if(desc->getFieldMask() & changedI->second)
743 if(!mask.empty())
744 mask += "<br>";
745 mask += desc->getName().str();
750 if(!col)
751 os << "<tr>";
752 os << "<td>"
753 << createFCViewReference(fcPtr)
754 << "</td><td>"
755 << mask
756 << "</td>";
757 col = (col+1) % changedCols;
758 if(!col)
759 os << "</tr>\n";
761 while(col && col++ < changedCols)
762 os << "<td>&nbsp;</td>";
763 os << "</tr>\n</table>\n";
765 // destroyed
766 os << "<h2>Destroyed</h2>"
767 << "<table><tr>";
768 for(col = 0 ; col < destroyedCols ; ++col)
769 os << "<th>FieldContainer</th>";
770 os << "</tr>\n";
771 for(col = 0,destroyedI = changeList->beginDestroyed();
772 destroyedI != changeList->endDestroyed(); destroyedI++)
774 fcPtr = FieldContainerFactory::the()->getContainer(*destroyedI);
775 if(!col)
776 os << "<tr>";
777 os << "<td>" << createFCViewReference(fcPtr,*destroyedI) << "</td>";
778 col = (col+1) % destroyedCols;
779 if(!col)
780 os << "</tr>\n";
782 while(col && col++ < destroyedCols)
783 os << "<td>&nbsp;</td>";
784 os << "</tr>\n</table>\n";
785 os << _footer << "</html>";
786 #endif
789 /*! FieldContainer view handler
792 void WebInterface::fcViewHandler( std::ostream &os,
793 const char *,
794 ParameterT &param)
796 FieldContainer *fcPtr;//,*childFc;
797 std::string type,value;
798 UInt32 id;
799 // Field *field;
800 // MFFieldContainerPtr *mfFCPtr;
802 if(!getParam(param,"id"))
804 os << "Content-Type: text/html\r\n"
805 "\r\n"
806 "<html>"
807 << _header
808 << "id missing"
809 << _footer << "</html>";
810 return;
813 id = atoi(getParam(param,"id"));
815 os << "Content-Type: text/html\r\n"
816 "\r\n"
817 "<html>"
818 << _header;
820 fcPtr = FieldContainerFactory::the()->getContainer(id);
822 if(fcPtr == NULL)
824 os << "NullFC";
826 else
828 os << "<h1>"
829 << fcPtr->getTypeName()
830 << " " << getNodeName(fcPtr)
831 << "</h1>"
832 << "<table><tr><th>Field</th><th>Field Type</th><th>&nbsp;</th>"
833 << "<th>Value</th></tr>\n";
836 UInt32 numFields = fcPtr->getNumFields();
838 for(UInt32 field = 1; field <= numFields; field++)
840 GetFieldHandlePtr fHandle = fcPtr->getField(field);
842 if(fHandle == NULL || fHandle->isValid() == false)
844 continue;
847 os << "<tr><td>"
848 << fHandle->getName()
849 << "</td><td>"
850 << fHandle->getType().getCName()
851 << "</td><td>";
853 GetMapFieldHandlePtr sfMap =
854 boost::dynamic_pointer_cast<GetMapFieldHandle>(fHandle);
856 FieldContainerPtrSFieldBase::GetHandlePtr sfFCPtr =
857 boost::dynamic_pointer_cast<
858 FieldContainerPtrSFieldBase::GetHandle>(fHandle);
860 FieldContainerPtrMFieldBase::GetHandlePtr mfFCPtr =
861 boost::dynamic_pointer_cast<
862 FieldContainerPtrMFieldBase::GetHandle>(fHandle);
864 if(sfMap != NULL && sfMap->isValid() == true)
866 os << "</td><td>\n";
867 #if 0
868 AttachmentMap &am = static_cast<SFAttachmentMap *>(field)->getValue();
869 AttachmentMap::const_iterator mI;
870 for(mI = am.begin() ; mI != am.end() ; ++mI)
872 if(mI != am.begin())
873 os << "\n<br>";
874 os << createFCViewReference(mI->second);
876 #endif
878 else
880 if(sfFCPtr != NULL || mfFCPtr != NULL)
882 os << "</td><td>\n";
884 if(mfFCPtr != NULL && mfFCPtr->isValid() == true)
886 UInt32 mfSize = (*mfFCPtr)->size();
888 for(UInt32 j = 0 ; j < mfSize; ++j)
890 if(j>0)
891 os << "\n<br>";
893 os << createFCViewReference((*(*mfFCPtr))[j]);
896 else if(sfFCPtr != NULL && sfFCPtr->isValid() == true)
898 os << createFCViewReference((*sfFCPtr)->getValue());
901 else
903 OutStream outstream(os);
905 os << "<form action=\"fcedit\">"
906 << "<input type=\"submit\" value=\"Edit\">"
907 << "<input type=\"hidden\" name=\"id\" value=\""
908 << fcPtr->getId()
909 << "\">"
910 << "<input type=\"hidden\" name=\"field\" value=\""
911 << fHandle->getDescription()->getFieldId()
912 << "\">"
913 << "</form>"
914 << "</td><td>\n";
916 fHandle->pushValueToStream(outstream); // << value;
920 os << "</td></tr>\n";
923 os << "</table>";
926 os << _footer << "</html>";
929 /*! Edit field value
932 void WebInterface::fcEditHandler(std::ostream &os,
933 const char *,
934 ParameterT &param)
936 FieldContainer *fcPtr = NULL;
937 std::string value = "";
938 UInt32 cid = 0;
939 UInt32 fid = 0;
940 GetFieldHandlePtr fHandle;
941 FieldDescriptionBase *desc = NULL;
943 if(getParam(param,"id"))
945 cid = atoi(getParam(param,"id"));
947 fcPtr = FieldContainerFactory::the()->getContainer(cid);
950 if(getParam(param,"field"))
952 fid = atoi(getParam(param,"field"));
955 if(fcPtr == NULL)
957 os << "Content-Type: text/html\r\n"
958 "\r\n"
959 "<html>" << _header
960 << "Unknown field container"
961 << _footer << "</html>";
963 return;
966 fHandle = fcPtr->getField(fid);
968 if(fHandle == NULL || fHandle->isValid() == false)
970 os << "Content-Type: text/html\r\n"
971 "\r\n"
972 "<html>" << _header
973 << "Unknown field in container"
974 << _footer << "</html>";
976 return;
979 desc = fcPtr->getFieldDescription(fid);
981 if(getParam(param, "value"))
983 EditFieldHandlePtr curField = fcPtr->editField(fid);
985 if(curField != NULL && curField->isValid() == true)
986 curField->pushValueFromCString(getParam(param, "value"));
989 std::stringstream ss;
991 OutStream oss(ss);
993 fHandle->pushValueToStream(oss);
995 value = ss.str();
998 os << "Content-Type: text/html\r\n"
999 "\r\n"
1000 "<html>" << _header
1001 << "<h1>Edit "
1002 << fcPtr->getTypeName()
1003 << "."
1004 << desc->getName()
1005 << "</h1>\n"
1006 << "<form action=\"fcedit\">"
1007 << "<textarea name=\"value\" cols=\"50\" rows=\"10\">"
1008 << value
1009 << "</textarea><p>"
1010 << "<input type=\"submit\" value=\" Change \">"
1011 << "<input type=\"hidden\" name=\"id\" value=\""
1012 << cid
1013 << "\">"
1014 << "<input type=\"hidden\" name=\"field\" value=\""
1015 << fid
1016 << "\">"
1017 << "</form>"
1018 << _footer << "</html>";
1021 /*! Show scenegraph tree. For each leave to open, a parameter with
1022 the container id must be set. The parameters open and closed
1023 are used to open or close folders.
1025 void WebInterface::treeViewHandler( std::ostream &os,
1026 const char *,
1027 ParameterT &param)
1029 ParameterT::iterator pI;
1031 // open folder
1032 if(getParam(param,"open"))
1034 setParam(param,getParam(param,"open"),"");
1035 setParam(param,"open",NULL);
1038 // close folder
1039 if(getParam(param,"close"))
1041 setParam(param,getParam(param,"close"),NULL);
1042 setParam(param,"close",NULL);
1045 // Changed
1046 os << "Content-Type: text/html\r\n"
1047 "\r\n"
1048 "<html>" << _header
1049 << "<h1>Scenegraph</h1>\n"
1050 << "<ul>\n";
1052 treeViewNode(os,_root,param);
1054 os << "</ul>"
1055 << _footer << "</html>";
1058 /*! Returns the name of a field container.
1060 const char *WebInterface::getNodeName(const FieldContainer *fcPtr)
1062 static const char *unnamed = "";
1064 if(fcPtr == NULL)
1065 return unnamed;
1067 const AttachmentContainer *acPtr =
1068 dynamic_cast<const AttachmentContainer *>(fcPtr);
1070 if(acPtr == NULL)
1071 return unnamed;
1073 const Char8 *name = getName(acPtr);
1075 if(name == NULL)
1076 return unnamed;
1078 return name;
1081 /*! Returns the default html header.
1083 std::string WebInterface::getDefaultHeader(void)
1085 std::stringstream header;
1087 header << "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" "
1088 << "width=\"100%\">"
1089 << "<tr bgcolor=\"#E5E5E5\">"
1090 << "<td valign=center><a href=\"/\"><font color=\"#004faf\">"
1091 << "Home</font></a></td>"
1092 << "<td valign=center><a href=\"changelist\"><font color="
1093 << "\"#004faf\">Changelist</font></a></td>"
1094 << "<td valign=center><a href=\"treeview\"><font color"
1095 << "=\"#004faf\">Scenegraph</font></a></td>"
1096 << "</tr></table>";
1098 return header.str();