Back to index

openldap  2.4.31
Public Member Functions | Private Member Functions | Private Attributes
LdifReader Class Reference

#include <LdifReader.h>

Collaboration diagram for LdifReader:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 LdifReader (std::istream &input)
bool isEntryRecords () const
bool isChangeRecords () const
int getVersion () const
LDAPEntry getEntryRecord ()
int readNextRecord (bool first=false)

Private Member Functions

int getLdifLine (std::string &line)
void splitLine (const std::string &line, std::string &type, std::string &value) const
std::string readIncludeLine (const std::string &line) const

Private Attributes

std::istream & m_ldifstream
LdifRecord m_currentRecord
int m_version
int m_curRecType
int m_lineNumber
bool m_ldifTypeRequest
bool m_currentIsFirst

Detailed Description

Definition at line 15 of file LdifReader.h.


Constructor & Destructor Documentation

LdifReader::LdifReader ( std::istream &  input)

Definition at line 23 of file LdifReader.cpp.

        : m_ldifstream(input), m_lineNumber(0)
{
    DEBUG(LDAP_DEBUG_TRACE, "<> LdifReader::LdifReader()" << std::endl);
    this->m_version = 0;
    // read the first record to find out version and type of the LDIF
    this->readNextRecord(true);
    this->m_currentIsFirst = true;
}

Here is the call graph for this function:


Member Function Documentation

Definition at line 180 of file LdifReader.cpp.

{
    std::list<stringpair>::const_iterator i = m_currentRecord.begin();
    if ( m_curRecType != LDAPMsg::SEARCH_ENTRY )
    {
        throw( std::runtime_error( "The LDIF record: '" + i->second +
                                   "' is not a valid LDAP Entry" ));
    }
    LDAPEntry resEntry(i->second);
    i++;
    LDAPAttribute curAttr(i->first);
    LDAPAttributeList *curAl = new LDAPAttributeList();
    for ( ; i != m_currentRecord.end(); i++ )
    {
        if ( i->first == curAttr.getName() )
        {
            curAttr.addValue(i->second);
        }
        else
        {
            const LDAPAttribute* existing = curAl->getAttributeByName( i->first );
            if ( existing )
            {
                // Attribute exists already (handle gracefully)
                curAl->addAttribute( curAttr );
                curAttr = LDAPAttribute( *existing );
                curAttr.addValue(i->second);
                curAl->delAttribute( i->first );
            }
            else
            {
                curAl->addAttribute( curAttr );
                curAttr = LDAPAttribute( i->first, i->second );
            }
        }
    }
    curAl->addAttribute( curAttr );
    resEntry.setAttributes( curAl );
    return resEntry;
}

Here is the call graph for this function:

int LdifReader::getLdifLine ( std::string &  line) [private]

Definition at line 221 of file LdifReader.cpp.

{
    DEBUG(LDAP_DEBUG_TRACE, "-> LdifReader::getLdifLine()" << std::endl);

    this->m_lineNumber++;
    if ( ! getline(m_ldifstream, ldifline) )
    {
        return -1;
    }
    while ( m_ldifstream &&
        (m_ldifstream.peek() == ' ' || m_ldifstream.peek() == '\t'))
    {
        std::string cat;
        m_ldifstream.ignore();
        getline(m_ldifstream, cat);
        ldifline += cat;
        this->m_lineNumber++;
    }

    DEBUG(LDAP_DEBUG_TRACE, "<- LdifReader::getLdifLine()" << std::endl);
    return 0;
}

Here is the caller graph for this function:

int LdifReader::getVersion ( ) const [inline]

Definition at line 30 of file LdifReader.h.

        {
            return m_version;
        }
bool LdifReader::isChangeRecords ( ) const [inline]

Definition at line 25 of file LdifReader.h.

        {
            return m_ldifTypeRequest;
        }
bool LdifReader::isEntryRecords ( ) const [inline]

Definition at line 20 of file LdifReader.h.

        {
            return !m_ldifTypeRequest;
        }
std::string LdifReader::readIncludeLine ( const std::string &  line) const [private]

Definition at line 328 of file LdifReader.cpp.

{
    std::string::size_type pos = sizeof("file:") - 1;
    std::string scheme = line.substr( 0, pos );
    std::string file;

    // only file:// URLs supported currently
    if ( scheme != "file:" )
    {
        DEBUG( LDAP_DEBUG_TRACE, "unsupported scheme: " << scheme 
                << std::endl);
    }
    else if ( line[pos] == '/' )
    {
        if ( line[pos+1] == '/' )
        {
            pos += 2;
        }
        file = line.substr(pos, std::string::npos);
        DEBUG( LDAP_DEBUG_TRACE, "target file: " << file << std::endl);
    }
    return file;
}
int LdifReader::readNextRecord ( bool  first = false)

Definition at line 33 of file LdifReader.cpp.

{
    DEBUG(LDAP_DEBUG_TRACE, "-> LdifReader::readRecord()" << std::endl);
    std::string line;
    std::string type;
    std::string value;
    int numLine = 0;
    int recordType = 0;

    if ( (! first) && this->m_currentIsFirst == true )
    {
        this->m_currentIsFirst = false;
        return m_curRecType;
    }

    m_currentRecord.clear();

    while ( !this->getLdifLine(line) )
    {
        DEBUG(LDAP_DEBUG_TRACE, "  Line: " << line << std::endl );

        // skip comments and empty lines between entries
        if ( line[0] == '#' || ( numLine == 0 && line.size() == 0 ) )
        {
            DEBUG(LDAP_DEBUG_TRACE, "skipping empty line or comment" << std::endl );
            continue;
        }
        if ( line.size() == 0 ) 
        {
            // End of Entry
            break;
        }

        this->splitLine(line, type, value);

        if ( numLine == 0 )
        {
            if ( type == "version" )
            {
                std::istringstream valuestream(value);
                valuestream >> this->m_version;
                if ( this->m_version != 1 ) // there is no other Version than LDIFv1 
                {
                    std::ostringstream err;
                    err << "Line " << this->m_lineNumber 
                        << ": Unsuported LDIF Version";
                    throw( std::runtime_error(err.str()) );
                }
                continue;
            }
            if ( type == "dn" ) // Record should start with the DN ...
            {
                DEBUG(LDAP_DEBUG_TRACE, " Record DN:" << value << std::endl);
            }
            else if ( type == "include" ) // ... or it might be an "include" line
            {
                DEBUG(LDAP_DEBUG_TRACE, " Include directive: " << value << std::endl);
                if ( this->m_version == 1 )
                {
                    std::ostringstream err;
                    err << "Line " << this->m_lineNumber 
                        << ": \"include\" not allowed in LDIF version 1.";
                    throw( std::runtime_error(err.str()) );
                }
                else
                {
                    std::ostringstream err;
                    err << "Line " << this->m_lineNumber 
                        << ": \"include\" not yet suppported.";
                    throw( std::runtime_error(err.str()) );
                }
            }
            else
            {
                DEBUG(LDAP_DEBUG_TRACE, " Record doesn't start with a DN" 
                            << std::endl);
                std::ostringstream err;
                err << "Line " << this->m_lineNumber 
                    << ": LDIF record does not start with a DN.";
                throw( std::runtime_error(err.str()) );
            }
        }
        if ( numLine == 1 ) // might contain "changtype" to indicate a change request
        {
            if ( type == "changetype" ) 
            {
                if ( first ) 
                {
                    this->m_ldifTypeRequest = true;
                }
                else if (! this->m_ldifTypeRequest )
                {
                    // Change Request in Entry record LDIF, should we accept it?
                    std::ostringstream err;
                    err << "Line " << this->m_lineNumber 
                        << ": Change Request in an entry-only LDIF.";
                    throw( std::runtime_error(err.str()) );
                }
                if ( value == "modify" )
                {
                    recordType = LDAPMsg::MODIFY_REQUEST;
                }
                else if ( value == "add" )
                {
                    recordType = LDAPMsg::ADD_REQUEST;
                }
                else if ( value == "delete" )
                {
                    recordType = LDAPMsg::DELETE_REQUEST;
                }
                else if ( value == "modrdn" )
                {   
                    recordType = LDAPMsg::MODRDN_REQUEST;
                }
                else
                {
                    DEBUG(LDAP_DEBUG_TRACE, " Unknown change request <" 
                            << value << ">" << std::endl);
                    std::ostringstream err;
                    err << "Line " << this->m_lineNumber 
                        << ": Unknown changetype: \"" << value << "\".";
                    throw( std::runtime_error(err.str()) );
                }
            }
            else
            {
                if ( first ) 
                {
                    this->m_ldifTypeRequest = false;
                }
                else if (this->m_ldifTypeRequest )
                {
                    // Entry record in Change record LDIF, should we accept 
                    // it (e.g. as AddRequest)?
                }
                recordType = LDAPMsg::SEARCH_ENTRY;
            }
        }
        m_currentRecord.push_back( stringpair(type, value) );
        numLine++;
    }
    DEBUG(LDAP_DEBUG_TRACE, "<- LdifReader::readRecord() return: " 
            << recordType << std::endl);
    m_curRecType = recordType;
    return recordType;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void LdifReader::splitLine ( const std::string &  line,
std::string &  type,
std::string &  value 
) const [private]

Definition at line 244 of file LdifReader.cpp.

{
    std::string::size_type pos = line.find(':');
    if ( pos == std::string::npos )
    {
        DEBUG(LDAP_DEBUG_ANY, "Invalid LDIF line. No `:` separator" 
                << std::endl );
        std::ostringstream err;
        err << "Line " << this->m_lineNumber << ": Invalid LDIF line. No `:` separator";
        throw( std::runtime_error( err.str() ));
    }

    type = line.substr(0, pos);
    if ( pos == line.size() )
    {
        // empty value
        value = "";
        return;
    }

    pos++;
    char delim = line[pos];
    if ( delim == ':' || delim == '<' )
    {
        pos++;
    }

    for( ; pos < line.size() && isspace(line[pos]); pos++ )
    { /* empty */ }

    value = line.substr(pos);

    if ( delim == ':' )
    {
        // Base64 encoded value
        DEBUG(LDAP_DEBUG_TRACE, "  base64 encoded value" << std::endl );
        char outbuf[value.size()];
        int rc = sasl_decode64(value.c_str(), value.size(), 
                outbuf, value.size(), NULL);
        if( rc == SASL_OK )
        {
            value = std::string(outbuf);
        }
        else if ( rc == SASL_BADPROT )
        {
            value = "";
            DEBUG( LDAP_DEBUG_TRACE, " invalid base64 content" << std::endl );
            std::ostringstream err;
            err << "Line " << this->m_lineNumber << ": Can't decode Base64 data";
            throw( std::runtime_error( err.str() ));
        }
        else if ( rc == SASL_BUFOVER )
        {
            value = "";
            DEBUG( LDAP_DEBUG_TRACE, " not enough space in output buffer" 
                    << std::endl );
            std::ostringstream err;
            err << "Line " << this->m_lineNumber 
                << ": Can't decode Base64 data. Buffer too small";
            throw( std::runtime_error( err.str() ));
        }
    }
    else if ( delim == '<' )
    {
        // URL value
        DEBUG(LDAP_DEBUG_TRACE, "  url value" << std::endl );
        std::ostringstream err;
        err << "Line " << this->m_lineNumber 
            << ": URLs are currently not supported";
        throw( std::runtime_error( err.str() ));
    }
    else 
    {
        // "normal" value
        DEBUG(LDAP_DEBUG_TRACE, "  string value" << std::endl );
    }
    DEBUG(LDAP_DEBUG_TRACE, "  Type: <" << type << ">" << std::endl );
    DEBUG(LDAP_DEBUG_TRACE, "  Value: <" << value << ">" << std::endl );
    return;
}

Here is the caller graph for this function:


Member Data Documentation

Definition at line 51 of file LdifReader.h.

Definition at line 54 of file LdifReader.h.

Definition at line 49 of file LdifReader.h.

std::istream& LdifReader::m_ldifstream [private]

Definition at line 48 of file LdifReader.h.

Definition at line 53 of file LdifReader.h.

Definition at line 52 of file LdifReader.h.

Definition at line 50 of file LdifReader.h.


The documentation for this class was generated from the following files: