(file) Return to CIMResponseData.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/CIMResponseData.cpp between version 1.2.2.18 and 1.9.2.1

version 1.2.2.18, 2009/11/18 07:26:30 version 1.9.2.1, 2012/05/25 13:04:22
Line 103 
Line 103 
     return _binaryData;     return _binaryData;
 } }
  
 bool CIMResponseData::setBinary(CIMBuffer& in, bool hasLen)  bool CIMResponseData::setBinary(CIMBuffer& in)
 { {
     PEG_METHOD_ENTER(TRC_DISPATCHER,      PEG_METHOD_ENTER(TRC_DISPATCHER, "CIMResponseData::setBinary");
         "CIMResponseData::setBinary");  
  
     if (hasLen)      // Append all serial data from the CIMBuffer to the local data store.
     {      // Returns error if input not a serialized Uint8A
         if (!in.getUint8A(_binaryData))         if (!in.getUint8A(_binaryData))
         {         {
             PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,             PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
                 "Failed to get binary object path data!");              "Failed to get binary input data!");
             PEG_METHOD_EXIT();             PEG_METHOD_EXIT();
             return false;             return false;
         }         }
       _encoding |= RESP_ENC_BINARY;
       PEG_METHOD_EXIT();
       return true;
     }     }
     else  
   bool CIMResponseData::setRemainingBinaryData(CIMBuffer& in)
     {     {
         size_t remainingDataLength = in.capacity() - in.size();      PEG_METHOD_ENTER(TRC_DISPATCHER, "CIMResponseData::setRemainingBinaryData");
   
       // Append any data that has not been deserialized already from
       // the CIMBuffer.
       size_t remainingDataLength = in.remainingDataLength();
         _binaryData.append((Uint8*)in.getPtr(), remainingDataLength);         _binaryData.append((Uint8*)in.getPtr(), remainingDataLength);
     }  
     _encoding |= RESP_ENC_BINARY;     _encoding |= RESP_ENC_BINARY;
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
     return true;     return true;
Line 304 
Line 311 
 { {
     PEG_METHOD_ENTER(TRC_DISPATCHER,     PEG_METHOD_ENTER(TRC_DISPATCHER,
         "CIMResponseData::encodeBinaryResponse");         "CIMResponseData::encodeBinaryResponse");
   
     // Need to do a complete job here by transferring all contained data     // Need to do a complete job here by transferring all contained data
     // into binary format and handing it out in the CIMBuffer     // into binary format and handing it out in the CIMBuffer
     if (RESP_ENC_BINARY == (_encoding & RESP_ENC_BINARY))     if (RESP_ENC_BINARY == (_encoding & RESP_ENC_BINARY))
Line 320 
Line 326 
         {         {
             case RESP_INSTNAMES:             case RESP_INSTNAMES:
             {             {
                 out.putObjectPathA(_instanceNames, false);                  out.putObjectPathA(_instanceNames);
                 break;                 break;
             }             }
             case RESP_INSTANCE:             case RESP_INSTANCE:
Line 329 
Line 335 
                 {                 {
                     _instances.append(CIMInstance());                     _instances.append(CIMInstance());
                 }                 }
                 out.putInstance(_instances[0], false, false);                  out.putInstance(_instances[0], true, true);
                 break;                 break;
             }             }
             case RESP_INSTANCES:             case RESP_INSTANCES:
             {             {
                 out.putInstanceA(_instances, false);                  out.putInstanceA(_instances);
                 break;                 break;
             }             }
             case RESP_OBJECTS:             case RESP_OBJECTS:
Line 344 
Line 350 
             }             }
             case RESP_OBJECTPATHS:             case RESP_OBJECTPATHS:
             {             {
                 out.putObjectPathA(_instanceNames, false);                  out.putObjectPathA(_instanceNames);
                 break;                 break;
             }             }
             default:             default:
Line 370 
Line 376 
 void CIMResponseData::completeNamespace(const SCMOInstance * x) void CIMResponseData::completeNamespace(const SCMOInstance * x)
 { {
     const char * ns;     const char * ns;
     Uint64 len;      Uint32 len;
     ns = x->getNameSpace_l(len);     ns = x->getNameSpace_l(len);
     // Both internal XML as well as binary always contain a namespace     // Both internal XML as well as binary always contain a namespace
     // don't have to do anything for those two encodings     // don't have to do anything for those two encodings
     if ((RESP_ENC_BINARY == (_encoding&RESP_ENC_BINARY)) && (len != 0))     if ((RESP_ENC_BINARY == (_encoding&RESP_ENC_BINARY)) && (len != 0))
     {     {
         _defaultNamespace = (char*)malloc(len+1);          _defaultNamespace = CIMNamespaceName(ns);
         if (0==_defaultNamespace)  
         {  
             return;  
         }  
         memcpy(_defaultNamespace, ns, len+1);  
         _defaultNamespaceLen = len;  
     }     }
   
   
     if (RESP_ENC_CIM == (_encoding & RESP_ENC_CIM))     if (RESP_ENC_CIM == (_encoding & RESP_ENC_CIM))
     {     {
         CIMNamespaceName nsName(ns);         CIMNamespaceName nsName(ns);
Line 403 
Line 401 
                         p.setNameSpace(nsName);                         p.setNameSpace(nsName);
                     }                     }
                 }                 }
                   break;
             }             }
             case RESP_INSTANCES:             case RESP_INSTANCES:
             {             {
Line 469 
Line 468 
     const String & hn,     const String & hn,
     const CIMNamespaceName & ns)     const CIMNamespaceName & ns)
 { {
     // Only perform this operation when we have instantiated data.      if (RESP_ENC_BINARY == (_encoding & RESP_ENC_BINARY))
     // Do nothing for binary and internal xml data.      {
           // On binary need remember hostname and namespace in case someone
           // builds C++ default objects or Xml types from it later on
           // -> usage: See resolveBinary()
           _defaultNamespace=ns;
           _defaultHostname=hn;
       }
       // InternalXml does not support objectPath calls
       if ((RESP_ENC_XML == (_encoding & RESP_ENC_XML)) &&
               (RESP_OBJECTS == _dataType))
       {
           for (Uint32 j = 0, n = _referencesData.size(); j < n; j++)
           {
               if (0 == _hostsData[j].size())
               {
                   _hostsData[j]=hn;
               }
               if (_nameSpacesData[j].isNull())
               {
                   _nameSpacesData[j]=ns;
               }
           }
       }
     if (RESP_ENC_CIM == (_encoding & RESP_ENC_CIM))     if (RESP_ENC_CIM == (_encoding & RESP_ENC_CIM))
     {     {
         switch (_dataType)         switch (_dataType)
Line 528 
Line 548 
                 for (Uint32 j = 0, n = _scmoInstances.size(); j < n; j++)                 for (Uint32 j = 0, n = _scmoInstances.size(); j < n; j++)
                 {                 {
                     SCMOInstance & scmoInst=_scmoInstances[j];                     SCMOInstance & scmoInst=_scmoInstances[j];
                     if (0 == scmoInst.getHostName())                      scmoInst.completeHostNameAndNamespace(
                     {                          hnChars,
                         scmoInst.setHostName_l(hnChars,hnLen);                          hnLen,
                     }                          nsChars,
                     if (0 == scmoInst.getNameSpace())                          nsLen);
                     {  
                         scmoInst.setNameSpace_l(nsChars,nsLen);  
                     }  
                 }                 }
                 break;                 break;
             }             }
Line 550 
Line 567 
 void CIMResponseData::encodeXmlResponse(Buffer& out) void CIMResponseData::encodeXmlResponse(Buffer& out)
 { {
     PEG_TRACE((TRC_XML, Tracer::LEVEL3,     PEG_TRACE((TRC_XML, Tracer::LEVEL3,
         "CIMResponseData::encodeXmlResponse(encoding=%X,content=%X)\n",          "CIMResponseData::encodeXmlResponse(encoding=%X,content=%X)",
         _encoding,         _encoding,
         _dataType));         _dataType));
  
Line 561 
Line 578 
     {     {
         _resolveBinary();         _resolveBinary();
     }     }
   
     if (RESP_ENC_XML == (_encoding & RESP_ENC_XML))     if (RESP_ENC_XML == (_encoding & RESP_ENC_XML))
     {     {
         switch (_dataType)         switch (_dataType)
Line 590 
Line 606 
             {             {
                 const Array<ArraySint8>& a = _instanceData;                 const Array<ArraySint8>& a = _instanceData;
                 const Array<ArraySint8>& b = _referencesData;                 const Array<ArraySint8>& b = _referencesData;
   
                 for (Uint32 i = 0, n = a.size(); i < n; i++)                 for (Uint32 i = 0, n = a.size(); i < n; i++)
                 {                 {
                     out << STRLIT("<VALUE.OBJECTWITHPATH>\n");                     out << STRLIT("<VALUE.OBJECTWITHPATH>\n");
                     out.append((char*)b[i].getData(), b[i].size() - 1);                      out << STRLIT("<INSTANCEPATH>\n");
                       XmlWriter::appendNameSpacePathElement(
                               out,
                               _hostsData[i],
                               _nameSpacesData[i]);
                       // Leave out the surrounding tags "<VALUE.REFERENCE>\n"
                       // and "</VALUE.REFERENCE>\n" which are 18 and 19 characters
                       // long
                       out.append(
                           ((char*)b[i].getData())+18,
                           b[i].size() - 1 - 18 -19);
                       out << STRLIT("</INSTANCEPATH>\n");
                       // append instance body
                     out.append((char*)a[i].getData(), a[i].size() - 1);                     out.append((char*)a[i].getData(), a[i].size() - 1);
                     out << STRLIT("</VALUE.OBJECTWITHPATH>\n");                     out << STRLIT("</VALUE.OBJECTWITHPATH>\n");
                 }                 }
Line 627 
Line 654 
             {             {
                 if (_instances.size() > 0)                 if (_instances.size() > 0)
                 {                 {
                     XmlWriter::appendInstanceElement(out, _instances[0]);                      XmlWriter::appendInstanceElement(
                           out,
                           _instances[0],
                           _includeQualifiers,
                           _includeClassOrigin,
                           _propertyList);
                 }                 }
                 break;                 break;
             }             }
Line 636 
Line 668 
                 for (Uint32 i = 0, n = _instances.size(); i < n; i++)                 for (Uint32 i = 0, n = _instances.size(); i < n; i++)
                 {                 {
                     XmlWriter::appendValueNamedInstanceElement(                     XmlWriter::appendValueNamedInstanceElement(
                         out, _instances[i]);                          out,
                           _instances[i],
                           _includeQualifiers,
                           _includeClassOrigin,
                           _propertyList);
                 }                 }
                 break;                 break;
             }             }
Line 646 
Line 682 
                 {                 {
                     XmlWriter::appendValueObjectWithPathElement(                     XmlWriter::appendValueObjectWithPathElement(
                         out,                         out,
                         _objects[i]);                          _objects[i],
                           _includeQualifiers,
                           _includeClassOrigin,
                           _propertyList);
                 }                 }
                 break;                 break;
             }             }
Line 680 
Line 719 
                     SCMOXmlWriter::appendInstanceNameElement(                     SCMOXmlWriter::appendInstanceNameElement(
                         out,                         out,
                         _scmoInstances[i]);                         _scmoInstances[i]);
   
                 }                 }
                 break;                 break;
             }             }
Line 687 
Line 727 
             {             {
                 if (_scmoInstances.size() > 0)                 if (_scmoInstances.size() > 0)
                 {                 {
                     SCMOXmlWriter::appendInstanceElement(out,_scmoInstances[0]);                      if(_propertyList.isNull())
                       {
                           Array<Uint32> emptyNodes;
                           SCMOXmlWriter::appendInstanceElement(
                               out,
                               _scmoInstances[0],
                               false,
                               emptyNodes);
                       }
                       else
                       {
                           Array<propertyFilterNodesArray_t> propFilterNodesArrays;
                           // This searches for an already created array of nodes,
                           //if not found, creates it inside propFilterNodesArrays
                           const Array<Uint32> & nodes=
                               SCMOXmlWriter::getFilteredNodesArray(
                                   propFilterNodesArrays,
                                   _scmoInstances[0],
                                   _propertyList);
                           SCMOXmlWriter::appendInstanceElement(
                               out,
                               _scmoInstances[0],
                               true,
                               nodes);
                       }
                 }                 }
                 break;                 break;
             }             }
             case RESP_INSTANCES:             case RESP_INSTANCES:
             {             {
                 for (Uint32 i = 0, n = _scmoInstances.size(); i < n; i++)                  SCMOXmlWriter::appendValueSCMOInstanceElements(
                 {  
                     SCMOXmlWriter::appendValueSCMOInstanceElement(  
                         out,                         out,
                         _scmoInstances[i]);                      _scmoInstances,
                 }                      _propertyList);
                 break;                 break;
             }             }
             case RESP_OBJECTS:             case RESP_OBJECTS:
             {             {
                 for (Uint32 i = 0; i < _scmoInstances.size(); i++)  
                 {  
                     SCMOXmlWriter::appendValueObjectWithPathElement(                     SCMOXmlWriter::appendValueObjectWithPathElement(
                         out,                         out,
                         _scmoInstances[i]);                     _scmoInstances,
                 }                    _propertyList);
                 break;                 break;
             }             }
             case RESP_OBJECTPATHS:             case RESP_OBJECTPATHS:
Line 737 
Line 797 
 void CIMResponseData::encodeInternalXmlResponse(CIMBuffer& out) void CIMResponseData::encodeInternalXmlResponse(CIMBuffer& out)
 { {
     PEG_TRACE((TRC_XML, Tracer::LEVEL3,     PEG_TRACE((TRC_XML, Tracer::LEVEL3,
         "CIMResponseData::encodeInternalXmlResponse(encoding=%X,content=%X)\n",          "CIMResponseData::encodeInternalXmlResponse(encoding=%X,content=%X)",
         _encoding,         _encoding,
         _dataType));         _dataType));
       // For mixed (CIM+SCMO) responses, we need to tell the receiver the
       // total number of instances. The totalSize variable is used to keep track
       // of this.
       Uint32 totalSize = 0;
  
     // already existing Internal XML does not need to be encoded further     // already existing Internal XML does not need to be encoded further
     // binary input is not actually impossible here, but we have an established     // binary input is not actually impossible here, but we have an established
Line 758 
Line 822 
                 if (0 == _instances.size())                 if (0 == _instances.size())
                 {                 {
                     _instances.append(CIMInstance());                     _instances.append(CIMInstance());
                       CIMInternalXmlEncoder::_putXMLInstance(
                           out,
                           _instances[0]);
                       break;
                 }                 }
                 CIMInternalXmlEncoder::_putXMLInstance(out, _instances[0]);                  CIMInternalXmlEncoder::_putXMLInstance(
                       out,
                       _instances[0],
                       _includeQualifiers,
                       _includeClassOrigin,
                       _propertyList);
                 break;                 break;
             }             }
             case RESP_INSTANCES:             case RESP_INSTANCES:
             {             {
                 Uint32 n = _instances.size();                 Uint32 n = _instances.size();
                 out.putUint32(n);                  totalSize = n + _scmoInstances.size();
                   out.putUint32(totalSize);
                 for (Uint32 i = 0; i < n; i++)                 for (Uint32 i = 0; i < n; i++)
                 {                 {
                     CIMInternalXmlEncoder::_putXMLNamedInstance(                     CIMInternalXmlEncoder::_putXMLNamedInstance(
                         out,                         out,
                         _instances[i]);                          _instances[i],
                           _includeQualifiers,
                           _includeClassOrigin,
                           _propertyList);
                 }                 }
                 break;                 break;
             }             }
             case RESP_OBJECTS:             case RESP_OBJECTS:
             {             {
                 Uint32 n = _objects.size();                 Uint32 n = _objects.size();
                 out.putUint32(n);                  totalSize = n + _scmoInstances.size();
                   out.putUint32(totalSize);
                 for (Uint32 i = 0; i < n; i++)                 for (Uint32 i = 0; i < n; i++)
                 {                 {
                     CIMInternalXmlEncoder::_putXMLObject(out, _objects[i]);                      CIMInternalXmlEncoder::_putXMLObject(
                           out,
                           _objects[i],
                           _includeQualifiers,
                           _includeClassOrigin,
                           _propertyList);
                 }                 }
                 break;                 break;
             }             }
Line 804 
Line 887 
                 {                 {
                     _scmoInstances.append(SCMOInstance());                     _scmoInstances.append(SCMOInstance());
                 }                 }
                 SCMOInternalXmlEncoder::_putXMLInstance(out, _scmoInstances[0]);                  SCMOInternalXmlEncoder::_putXMLInstance(
                       out,
                       _scmoInstances[0],
                       _propertyList);
                 break;                 break;
             }             }
             case RESP_INSTANCES:             case RESP_INSTANCES:
             {             {
                 Uint32 n = _scmoInstances.size();                 Uint32 n = _scmoInstances.size();
                 out.putUint32(n);                  // Only put the size when not already done above
                 for (Uint32 i = 0; i < n; i++)                  if (0==totalSize)
                 {                 {
                       out.putUint32(n);
                   }
                     SCMOInternalXmlEncoder::_putXMLNamedInstance(                     SCMOInternalXmlEncoder::_putXMLNamedInstance(
                             out,                             out,
                             _scmoInstances[i]);                      _scmoInstances,
                 }                      _propertyList);
                 break;                 break;
             }             }
             case RESP_OBJECTS:             case RESP_OBJECTS:
             {             {
                 Uint32 n = _scmoInstances.size();                 Uint32 n = _scmoInstances.size();
                 out.putUint32(n);                  // Only put the size when not already done above
                 for (Uint32 i = 0; i < n; i++)                  if (0==totalSize)
                 {                 {
                       out.putUint32(n);
                   }
                     SCMOInternalXmlEncoder::_putXMLObject(                     SCMOInternalXmlEncoder::_putXMLObject(
                         out,                         out,
                         _scmoInstances[i]);                      _scmoInstances,
                 }                      _propertyList);
                 break;                 break;
             }             }
             // internal xml encoding of instance names and object paths not             // internal xml encoding of instance names and object paths not
Line 841 
Line 931 
             }             }
         }         }
     }     }
   
 } }
  
 void CIMResponseData::_resolveToCIM() void CIMResponseData::_resolveToCIM()
 { {
     PEG_TRACE((TRC_XML, Tracer::LEVEL2,      PEG_TRACE((TRC_XML, Tracer::LEVEL3,
         "CIMResponseData::_resolveToCIM(encoding=%X,content=%X)\n",          "CIMResponseData::_resolveToCIM(encoding=%X,content=%X)",
         _encoding,         _encoding,
         _dataType));         _dataType));
  
Line 868 
Line 959 
  
 void CIMResponseData::_resolveToSCMO() void CIMResponseData::_resolveToSCMO()
 { {
     PEG_TRACE((TRC_XML, Tracer::LEVEL2,      PEG_TRACE((TRC_XML, Tracer::LEVEL3,
         "CIMResponseData::_resolveToSCMO(encoding=%X,content=%X)\n",          "CIMResponseData::_resolveToSCMO(encoding=%X,content=%X)",
         _encoding,         _encoding,
         _dataType));         _dataType));
  
Line 928 
Line 1019 
         {         {
             switch (_dataType)             switch (_dataType)
             {             {
                 // TODO: Decide what to decode based on marker  
                 case RESP_INSTNAMES:                 case RESP_INSTNAMES:
                 case RESP_OBJECTPATHS:                 case RESP_OBJECTPATHS:
                 {                 {
Line 995 
Line 1085 
             _encoding |= RESP_ENC_CIM;             _encoding |= RESP_ENC_CIM;
         } // else SCMO         } // else SCMO
     }     }
   
     _encoding &=(~RESP_ENC_BINARY);     _encoding &=(~RESP_ENC_BINARY);
       // fix up the hostname and namespace for objects if defaults
       // were set
       if (_defaultHostname.size() > 0 && !_defaultNamespace.isNull())
       {
           completeHostNameAndNamespace(_defaultHostname, _defaultNamespace);
       }
     in.release();     in.release();
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
 } }
Line 1006 
Line 1100 
 { {
     switch (_dataType)     switch (_dataType)
     {     {
         // same encoding for instance names and object paths          // Xml encoding for instance names and object paths not used
         case RESP_OBJECTPATHS:         case RESP_OBJECTPATHS:
         case RESP_INSTNAMES:         case RESP_INSTNAMES:
         {         {
             for (Uint32 i = 0; i < _referencesData.size(); i++)  
             {  
                 CIMObjectPath cop;  
                 // Deserialize path:  
                 {  
                     XmlParser parser((char*)_referencesData[i].getData());  
   
                     if (XmlReader::getInstanceNameElement(parser, cop))  
                     {  
                         if (!_nameSpacesData[i].isNull())  
                             cop.setNameSpace(_nameSpacesData[i]);  
   
                         if (_hostsData[i].size())  
                             cop.setHost(_hostsData[i]);  
                     }  
                 }  
                 _instanceNames.append(cop);  
             }  
             break;             break;
         }         }
         case RESP_INSTANCE:         case RESP_INSTANCE:
Line 1240 
Line 1316 
  
 void CIMResponseData::_resolveCIMToSCMO() void CIMResponseData::_resolveCIMToSCMO()
 { {
       CString nsCString=_defaultNamespace.getString().getCString();
       const char* _defNamespace = nsCString;
       Uint32 _defNamespaceLen;
       if (_defaultNamespace.isNull())
       {
           _defNamespaceLen=0;
       }
       else
       {
           _defNamespaceLen=strlen(_defNamespace);
       }
     switch (_dataType)     switch (_dataType)
     {     {
         case RESP_INSTNAMES:         case RESP_INSTNAMES:
Line 1248 
Line 1335 
             {             {
                 SCMOInstance addme(                 SCMOInstance addme(
                     _instanceNames[i],                     _instanceNames[i],
                     _defaultNamespace,                      _defNamespace,
                     _defaultNamespaceLen);                      _defNamespaceLen);
                 _scmoInstances.append(addme);                 _scmoInstances.append(addme);
             }             }
             _instanceNames.clear();             _instanceNames.clear();
Line 1261 
Line 1348 
             {             {
                 SCMOInstance addme(                 SCMOInstance addme(
                     _instances[0],                     _instances[0],
                     _defaultNamespace,                      _defNamespace,
                     _defaultNamespaceLen);                      _defNamespaceLen);
                 _scmoInstances.clear();                 _scmoInstances.clear();
                 _scmoInstances.append(addme);                 _scmoInstances.append(addme);
                 _instances.clear();                 _instances.clear();
Line 1275 
Line 1362 
             {             {
                 SCMOInstance addme(                 SCMOInstance addme(
                     _instances[i],                     _instances[i],
                     _defaultNamespace,                      _defNamespace,
                     _defaultNamespaceLen);                      _defNamespaceLen);
                 _scmoInstances.append(addme);                 _scmoInstances.append(addme);
             }             }
             _instances.clear();             _instances.clear();
Line 1288 
Line 1375 
             {             {
                 SCMOInstance addme(                 SCMOInstance addme(
                     _objects[i],                     _objects[i],
                     _defaultNamespace,                      _defNamespace,
                     _defaultNamespaceLen);                      _defNamespaceLen);
                 _scmoInstances.append(addme);                 _scmoInstances.append(addme);
             }             }
             _objects.clear();             _objects.clear();
Line 1301 
Line 1388 
             {             {
                 SCMOInstance addme(                 SCMOInstance addme(
                     _instanceNames[i],                     _instanceNames[i],
                     _defaultNamespace,                      _defNamespace,
                     _defaultNamespaceLen);                      _defNamespaceLen);
                 // TODO: More description about this.                 // TODO: More description about this.
                 if (0 == _instanceNames[i].getKeyBindings().size())                 if (0 == _instanceNames[i].getKeyBindings().size())
                 {                 {
Line 1326 
Line 1413 
     _encoding |=RESP_ENC_SCMO;     _encoding |=RESP_ENC_SCMO;
 } }
  
   void CIMResponseData::setRequestProperties(
       const Boolean includeQualifiers,
       const Boolean includeClassOrigin,
       const CIMPropertyList& propertyList)
   {
       _includeQualifiers = includeQualifiers;
       _includeClassOrigin = includeClassOrigin;
       _propertyList = propertyList;
   }
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.2.2.18  
changed lines
  Added in v.1.9.2.1

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2