Exemple #1
0
 def setup(self):
     self.log("Connecting to CIP... ")
     self.cip = CIP(Config['cumulus']['url'], Config['cumulus']['port'],
                    Config['cumulus']['user'],
                    Config['cumulus']['password'],
                    Config['cumulus']['location'])
     self.cip.load_layout(Config['cumulus']['layout'],
                          Config['cumulus']['layout'])
     self.log("OK.")
Exemple #2
0
def fuzz_classid(client, instanceid):
    status = {}
    for classid in range(0x64, 0xc8):
        data = "\x01\x00"
        # Symbol Instanc Addressing
        cippkt = CIP(service=0x4c,
                     path=CIP_Path.make(class_id=classid,
                                        instance_id=instanceid,
                                        word_size=3)) / data

        print("class id: " + str(hex(classid)) + " | instance id: " +
              str(hex(instanceid)),
              end='\r')
        try:
            client.send_unit_cip(cippkt)
        except:
            pass
        # Show the response only if it does not contain data
        resppkt = client.recv_enippkt()
        if resppkt is not None:
            stat = str(resppkt[CIP].status)
            if stat in status:
                status.get(stat).append(str(hex(classid)))
            else:
                status[stat] = [str(hex(classid))]
    # print all status
    for key, value in status.items():
        print("Status: " + key)
        for v in value:
            print("        " + v)
Exemple #3
0
    def read_full_tag(self, class_id, instance_id, total_size):
        """Read the content of a tag which can be quite big"""
        data_chunks = []
        offset = 0
        remaining_size = total_size

        while remaining_size > 0:
            cippkt = CIP(service=0x4c,
                         path=CIP_Path.make(class_id=class_id,
                                            instance_id=instance_id))
            cippkt /= CIP_ReqReadOtherTag(start=offset, length=remaining_size)
            self.send_rr_cm_cip(cippkt)
            if self.sock is None:
                return
            resppkt = self.recv_enippkt()

            cipstatus = resppkt[CIP].status[0].status
            received_data = str(resppkt[CIP].payload)
            if cipstatus == 0:
                # Success
                assert len(received_data) == remaining_size
            elif cipstatus == 6 and len(received_data) > 0:
                # Partial response (size too big)
                pass
            else:
                logger.error("Error in Read Tag response: %r",
                             resppkt[CIP].status[0])
                return

            # Remember the chunk and continue
            data_chunks.append(received_data)
            offset += len(received_data)
            remaining_size -= len(received_data)
        return b''.join(data_chunks)
Exemple #4
0
def main():
    # Connect to PLC
    client = plc.PLCClient('192.168.9.227')
    if not client.connected:
        sys.exit(1)

    # Creating Connections Through the Connection Manager Object
    if not client.forward_open():
        sys.exit(1)

    # Get_Instance_Attribute_List
    # Set initial instance to 0x0
    instanceid = 0x0
    # status
    status = ''
    # Number of attributes to retrieve (2 bytes) + Attribute 1 - Symbol Name (2 bytes) + Attribute 2 - Symbol Type (2 bytes)
    data = "\x02\x00\x01\x00\x02\x00"

    while ("Success" not in status):
        cippkt = CIP(service=0x55,
                     path=CIP_Path.make(class_id=0x6b,
                                        instance_id=instanceid,
                                        word_size=3)) / data
        client.send_unit_cip(cippkt)
        resppkt = client.recv_enippkt()
        status = str(resppkt[CIP].status)
        instanceid = parse_attributes(resppkt[CIP].load) + 1

    client.forward_close()
Exemple #5
0
def fuzz_timeout(client):
    for i in range(0xff):
        # i = 0x1
        print("Fuzzing timeout: " + str(hex(i)))
        # Construct an enip packet from raw
        enippkt = ENIP_TCP(session=client.session_id)
        # Symbol Instanc Addressing
        cippkt = CIP(service=0x4c,
                     path=CIP_Path.make(class_id=0x6b, instance_id=0x227))
        # interface handle, timeout, count, items
        enippkt /= ENIP_SendUnitData(
            timeout=i,
            items=[
                # type_id, length, connection id
                ENIP_SendUnitData_Item() /
                ENIP_ConnectionAddress(connection_id=client.enip_connid),
                # type_id, length, sequence
                ENIP_SendUnitData_Item() /
                ENIP_ConnectionPacket(sequence=client.sequence) / cippkt
            ])
        client.sequence += 1
        if client.sock is not None:
            client.sock.send(str(enippkt))
        # Show the response only if it does not contain data
        resppkt = client.recv_enippkt()
        if resppkt is not None:
            print("Status: " + str(resppkt[ENIP_TCP].status))
            print("TImeout: " + str(hex(resppkt[ENIP_SendUnitData].timeout)))
Exemple #6
0
def fuzz_instanceid(client, classid):
    status = {}
    data = "\x01\x00"
    for instanceid in range(0xffff):
        # Symbol Instanc Addressing
        cippkt = CIP(service=0x4c,
                     path=CIP_Path.make(class_id=classid,
                                        instance_id=instanceid,
                                        word_size=3)) / data

        # print("class id: " + str(hex(classid)) + " | instance id: " + str(hex(instanceid)), end='\r')
        try:
            client.send_unit_cip(cippkt)
        except:
            pass
        # Receive the response and show it
        resppkt = client.recv_enippkt()
        # print("class id: " + str(hex(classid)) + " | instance id: " + str(hex(instanceid)) + " Status: " + str(resppkt[CIP].status))
        if resppkt is not None:
            stat = str(resppkt[CIP].status)
            if stat in status:
                status.get(stat).append(str(hex(instanceid)))
            else:
                status[stat] = [str(hex(instanceid))]
    # print all status
    for key, value in status.items():
        print("Status: " + key)
        for v in value:
            print("        " + v)
Exemple #7
0
def simple_read_tag(client, pathsize, classid, instanceid):
    # Symbol Instanc Addressing
    data = "\x01\x00"
    cippkt = CIP(service=0x4c,
                 path=CIP_Path.make(class_id=classid,
                                    instance_id=instanceid,
                                    word_size=pathsize)) / data

    # Construct an enip packet from raw
    enippkt = ENIP_TCP(session=client.session_id)
    # interface handle, timeout, count, items
    enippkt /= ENIP_SendUnitData(
        interface_handle=0x0,
        items=[
            # type_id, length, connection id
            ENIP_SendUnitData_Item() /
            ENIP_ConnectionAddress(connection_id=client.enip_connid),
            # type_id, length, sequence
            ENIP_SendUnitData_Item() /
            ENIP_ConnectionPacket(sequence=client.sequence) / cippkt
        ])
    client.sequence += 1
    if client.sock is not None:
        client.sock.send(str(enippkt))

    enippkt.show()

    # Show the response only if it does not contain data
    resppkt = client.recv_enippkt()
    if resppkt is not None:
        print("Status: " + str(resppkt[CIP].status))
Exemple #8
0
    def forward_open(self):
        """Send a forward open request"""
        cippkt = CIP(service=0x54,
                     path=CIP_Path(wordsize=2, path=b'\x20\x06\x24\x01'))
        cippkt /= CIP_ReqForwardOpen(
            path_wordsize=10,
            path=
            b"\x01\x00\x34\x04\x00\x00\x00\x00\x00\x00\x00\x00\x91\x06\x54\x6f\x43\x4e\x43\x34"
        )
        #FOR CREATING PACKETS
        #Attempt to change Ethernet protocol
        #ToCell path (9):\x34\x04\x01\x00\x0e\x00\xb2\x00\x00\x01\x91\x06\x54\x6f\x43\x65\x6c\x6c
        #associated error: 0x0115
        #To CNC4 path (10): \x01\x00\x34\x04\x00\x00\x00\x00\x00\x00\x00\x00\x91\x06\x54\x6f\x43\x4e\x43\x34
        #associated error: 0x031e
        #j path (8): \x01\x01\x34\x04\x00\x00\x00\x00\x00\x00\x00\x00\x91\x01\x6a\x00
        #associated error: None!!!!!!
        #print(cippkt['TCP'])
        #End of attempt

        self.send_rr_cip(cippkt)
        resppkt = self.recv_enippkt()
        if self.sock is None:
            return
        cippkt = resppkt[CIP]
        if cippkt.status[0].status != 0:
            logger.error("Failed to Forward Open CIP connection: %r",
                         cippkt.status[0])
            return False
        assert isinstance(cippkt.payload, CIP_RespForwardOpen)
        self.enip_connid = cippkt.payload.OT_network_connection_id
        return True
Exemple #9
0
    def get_list_of_instances(self, class_id):
        """Use CIP service 0x4b to get a list of instances of the specified class"""
        start_instance = 0
        inst_list = []
        while True:
            cippkt = CIP(service=0x4b,
                         path=CIP_Path.make(class_id=class_id,
                                            instance_id=start_instance))
            self.send_rr_cm_cip(cippkt)
            if self.sock is None:
                return
            resppkt = self.recv_enippkt()

            # Decode a list of 32-bit integers
            data = str(resppkt[CIP].payload)
            for i in range(0, len(data), 4):
                inst_list.append(struct.unpack('<I', data[i:i + 4])[0])

            cipstatus = resppkt[CIP].status[0].status
            if cipstatus == 0:
                return inst_list
            elif cipstatus == 6:
                # Partial response, query again from the next instance
                start_instance = inst_list[-1] + 1
            else:
                logger.error("Error in Get Instance List response: %r",
                             resppkt[CIP].status[0])
                return
Exemple #10
0
    def setup(self):
        self.log("Connecting to CIP and loading layout...")
        self.cip = CIP(Config['cumulus']['url'], Config['cumulus']['port'],
                       Config['cumulus']['user'],
                       Config['cumulus']['password'],
                       Config['cumulus']['location'])
        self.cip.load_layout(Config['cumulus']['layout'],
                             Config['cumulus']['layout'])
        self.log("OK.")

        self.log("Creating index of transcribed...")
        self.transcribed = {}
        for erindring in self.cip.searchall(
                Config['cumulus']['catalog'],
                view=Config['cumulus']['catalog'],
                querystring=
                "Offentlig == true && 'Related Master Assets' * && Samlingsnavn == 'Erindring'"
        ):
            if "Erindringsnummer" in erindring:
                self.transcribed[erindring['Erindringsnummer']] = erindring
        self.log(f"OK. Created index of {len(self.transcribed)} transcribed.")
Exemple #11
0
 def forward_close(self):
     """Send a forward close request"""
     cippkt = CIP(service=0x4e, path=CIP_Path(wordsize=2, path=b'\x20\x06\x24\x01'))
     cippkt /= CIP_ReqForwardClose(path_wordsize=3, path=b"\x01\x00\x20\x02\x24\x01")
     self.send_rr_cip(cippkt)
     if self.sock is None:
         return
     resppkt = self.recv_enippkt()
     cippkt = resppkt[CIP]
     if cippkt.status[0].status != 0:
         logger.error("Failed to Forward Close CIP connection: %r", cippkt.status[0])
         return False
     return True
Exemple #12
0
 def set_attribute(self, class_id, instance, attr, value):
     """Set the value of attribute class/instance/attr"""
     path = CIP_Path.make(class_id=class_id, instance_id=instance)
     # User CIP service 4: Set_Attribute_List
     cippkt = CIP(service=4, path=path) / scapy_all.Raw(load=struct.pack('<HH', 1, attr) + value)
     self.send_rr_cm_cip(cippkt)
     if self.sock is None:
         return
     resppkt = self.recv_enippkt()
     cippkt = resppkt[CIP]
     if cippkt.status[0].status != 0:
         logger.error("CIP set attribute error: %r", cippkt.status[0])
         return False
     return True
Exemple #13
0
 def forward_open(self):
     """Send a forward open request"""
     cippkt = CIP(service=0x54, path=CIP_Path(wordsize=2, path=b'\x20\x06\x24\x01'))
     cippkt /= CIP_ReqForwardOpen(path_wordsize=3, path=b"\x01\x00\x20\x02\x24\x01")
     self.send_rr_cip(cippkt)
     resppkt = self.recv_enippkt()
     if self.sock is None:
         return
     cippkt = resppkt[CIP]
     if cippkt.status[0].status != 0:
         logger.error("Failed to Forward Open CIP connection: %r", cippkt.status[0])
         return False
     assert isinstance(cippkt.payload, CIP_RespForwardOpen)
     self.enip_connid = cippkt.payload.OT_network_connection_id
     return True
Exemple #14
0
def fuzz_pathsize(client, classid, instanceid):
    data = "\x01\x00"
    for pathsize in range(0xff):
        # Symbol Instanc Addressing
        cippkt = CIP(service=0x4c,
                     path=CIP_Path.make(class_id=classid,
                                        instance_id=instanceid,
                                        word_size=pathsize)) / data

        try:
            client.send_unit_cip(cippkt)
        except:
            pass

        # Show the response only if it does not contain data
        resppkt = client.recv_enippkt()
        if resppkt is not None:
            print("Status: " + str(resppkt[CIP].status))
Exemple #15
0
 def get_attribute(self, class_id, instance, attr):
     """Get an attribute for the specified class/instance/attr path"""
     # Get_Attribute_Single does not seem to work properly
     # path = CIP_Path.make(class_id=class_id, instance_id=instance, attribute_id=attr)
     # cippkt = CIP(service=0x0e, path=path)  # Get_Attribute_Single
     path = CIP_Path.make(class_id=class_id, instance_id=instance)
     cippkt = CIP(path=path) / CIP_ReqGetAttributeList(attrs=[attr])
     self.send_rr_cm_cip(cippkt)
     if self.sock is None:
         return
     resppkt = self.recv_enippkt()
     cippkt = resppkt[CIP]
     if cippkt.status[0].status != 0:
         logger.error("CIP get attribute error: %r", cippkt.status[0])
         return
     resp_getattrlist = str(cippkt.payload)
     assert resp_getattrlist[:2] == b'\x01\x00'  # Attribute count must be 1
     assert struct.unpack('<H', resp_getattrlist[2:4])[0] == attr  # First attribute
     assert resp_getattrlist[4:6] == b'\x00\x00'  # Status
     return resp_getattrlist[6:]
Exemple #16
0
def scan_one(class_name, instance_id, attribute_id=None):

    success_service = set()
    class_id = CLASS_CODES[class_name]

    for service_id in CLASS_SERVICE_MAP[class_name]:
        plc_client = plc.PLCClient(PLC_HOST)

        if not plc_client.connected:
            logging.error(("Cannot connect to server"))
            sys.exit(1)

        # Make packet detail
        cippkt = CIP(service=service_id,
                     path=CIP_Path.make(class_id=class_id,
                                        instance_id=instance_id,
                                        attribute_id=attribute_id))

        # Send a CIP request
        plc_client.send_rr_cip(cippkt)

        # Receive the response
        resppkt = plc_client.recv_enippkt()

        #resppkt.show()

        try:
            enip_tcp_status = resppkt["ENIP_TCP"].status
            cip_tcp_status = resppkt["CIP_ResponseStatus"].status
        except:
            cip_tcp_status = None

        if enip_tcp_status == 0x0 and cip_tcp_status == 0x0:  # SUCCESS
            success_service.add(service_id)

    logging.debug(("Class " + str(class_name) + " supports serives " +
                   str(success_service)))

    return success_service
        class_id = CLASS_CODES[class_name]

        for instance_id in range(INSTANCE_ID_RANGE[0], INSTANCE_ID_RANGE[1]):

            logging.basicConfig(format='[%(levelname)s] %(message)s',
                                level=logging.DEBUG)

            # Connect to PLC
            client = plc.PLCClient(PLC_HOST)
            if not client.connected:
                sys.exit(1)
            print("Established session {}".format(client.session_id))

            # Send a CIP ReadTag request
            cippkt = CIP(service=service_id,
                         path=CIP_Path.make(class_id=int(class_id),
                                            instance_id=instance_id))
            client.send_rr_cip(cippkt)

            # Receive the response and show it
            resppkt = client.recv_enippkt()

            enip_tcp_status = resppkt["ENIP_TCP"].status
            service_info = {
                "name": service_name + class_name + str(instance_id),
                "service_name": service_name,
                "class_name": class_name,
                "service_id": service_id,
                "class_id": class_id,
                "instance_id": instance_id
            }
Exemple #18
0
 def send_rr_cm_cip(self, cippkt):
     """Encapsulate the CIP packet into a ConnectionManager packet"""
     cipcm_msg = [cippkt]
     cippkt = CIP(path=CIP_Path.make(class_id=6, instance_id=1))
     cippkt /= CIP_ReqConnectionManager(message=cipcm_msg)
     self.send_rr_cip(cippkt)
Exemple #19
0
import logging
import sys

from cip import CIP, CIP_Path
import plc

logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.DEBUG)

# Connect to PLC
client = plc.PLCClient('192.168.6.70')
if not client.connected:
    sys.exit(1)
print("Established session {}".format(client.session_id))

if not client.forward_open():
    sys.exit(1)

# Send a CIP ReadTag request
cippkt = CIP(service=0x4c, path=CIP_Path.make_str("Raymond_INT"))
client.send_unit_cip(cippkt)

# Receive the response and show it
resppkt = client.recv_enippkt()
resppkt[CIP].show()

# Close the connection
client.forward_close()
Exemple #20
0
class ErindringerIndexer(IndexerBase):
    def __init__(self):
        super().__init__()
        self.progress_threshold = 0.1
        self.progress_threshold_next = self.progress_threshold
        self.commit_threshold = 100

    def collection_id(self):
        return 18

    def collection_info(self):
        return "Erindringer"

    def setup(self):
        self.log("Connecting to CIP and loading layout...")
        self.cip = CIP(Config['cumulus']['url'], Config['cumulus']['port'],
                       Config['cumulus']['user'],
                       Config['cumulus']['password'],
                       Config['cumulus']['location'])
        self.cip.load_layout(Config['cumulus']['layout'],
                             Config['cumulus']['layout'])
        self.log("OK.")

        self.log("Creating index of transcribed...")
        self.transcribed = {}
        for erindring in self.cip.searchall(
                Config['cumulus']['catalog'],
                view=Config['cumulus']['catalog'],
                querystring=
                "Offentlig == true && 'Related Master Assets' * && Samlingsnavn == 'Erindring'"
        ):
            if "Erindringsnummer" in erindring:
                self.transcribed[erindring['Erindringsnummer']] = erindring
        self.log(f"OK. Created index of {len(self.transcribed)} transcribed.")

    def get_total(self):
        search_result = self.cip.search(
            Config['cumulus']['catalog'],
            view=Config['cumulus']['catalog'],
            querystring=
            "Offentlig == true && 'Related Master Assets' !* && Samlingsnavn == 'Erindring'",
            maxreturned=1)
        return search_result['totalcount']

    def get_entries(self):
        return self.cip.searchall(
            Config['cumulus']['catalog'],
            view=Config['cumulus']['catalog'],
            querystring=
            "Offentlig == true && 'Related Master Assets' !* && Samlingsnavn == 'Erindring'",
            chunk=50)

    def handle_entry(self, erindring):
        jsonObj = {}
        jsonObj['id'] = "%d-%d" % (self.collection_id(), erindring['ID'])
        jsonObj['org_id'] = "%d" % erindring['ID']
        jsonObj['collection_id'] = self.collection_id()
        if "Fornavne" in erindring:
            jsonObj['firstnames'] = erindring['Fornavne']
        elif "Navn" in erindring and len(erindring['Navn'].split(',')) > 1:
            jsonObj['firstnames'] = erindring['Navn'].split(',')[1].strip()
        if "Efternavn" in erindring:
            jsonObj['lastname'] = erindring['Efternavn']
        elif "Navn" in erindring and len(erindring['Navn'].split(',')) > 0:
            jsonObj['lastname'] = erindring['Navn'].split(',')[0].strip()
        if "Stilling hovedperson" in erindring:
            jsonObj['position'] = erindring['Stilling hovedperson']
        if u"Stilling forældre" in erindring:
            jsonObj['position_parent'] = erindring[u'Stilling forældre']
        if u"Stilling ægtefælle" in erindring:
            jsonObj['position_spouse'] = erindring[u'Stilling ægtefælle']
        if "Periode" in erindring:
            jsonObj['period'] = erindring['Periode']
        if u"Fødselsår" in erindring:
            jsonObj[
                'yearOfBirth'] = erindring[u'Fødselsår'].year if isinstance(
                    erindring[u'Fødselsår'],
                    datetime.date) else erindring[u'Fødselsår']
        if "Description" in erindring:
            jsonObj['description'] = erindring['Description']
        if "Erindringsnummer" in erindring:
            jsonObj['erindring_number'] = erindring['Erindringsnummer']
        if u"Indsamlingsår" in erindring:
            jsonObj['collectedYear'] = erindring[u'Indsamlingsår']
        if "Omfang" in erindring:
            jsonObj['extent'] = erindring['Omfang']
        if u"Håndskrevne/maskinskreven" in erindring:
            jsonObj['writeMethod'] = erindring[u'Håndskrevne/maskinskreven']
        if "Document Name" in erindring:
            jsonObj['filename'] = erindring['Document Name']
        if "Transkriberet" in erindring:
            jsonObj['transcribed'] = erindring['Transkriberet']
            jsonObj[
                'transcribed_filename'] = erindring['Document Name'].replace(
                    ".pdf", "_transcribed.pdf"
                ) if erindring['Transkriberet'] and erindring[
                    'Document Name'] else None
        if "Civilstand" in erindring:
            jsonObj['civilstatus'] = erindring['Civilstand']
        if "Keywords" in erindring:
            jsonObj['keywords'] = erindring['Keywords'].split(",")
        if u"Køn" in erindring:
            jsonObj['sex'] = erindring[u'Køn']
        if "Erindringsnummer" in erindring and erindring[
                "Erindringsnummer"] in self.transcribed:
            jsonObj['transcribed_id'] = self.transcribed[
                erindring["Erindringsnummer"]]['ID']
        jsonObj['containsPhotos'] = 'Foto' in erindring and erindring['Foto']

        self.documents.append({
            'id':
            "%d-%d" % (self.collection_id(), erindring['ID']),
            'task_id':
            -1,
            'post_id':
            -1,
            'entry_id':
            -1,
            'user_id':
            -1,
            'user_name':
            ' ',
            'unit_id':
            -1,
            'page_id':
            -1,
            'jsonObj':
            json.dumps(jsonObj),
            'collection_id':
            self.collection_id(),
            'collection_info':
            self.collection_info(),
            'firstnames':
            erindring['Fornavne'] if 'Fornavne' in erindring else
            (erindring['Navn'].split(',')[1].strip() if 'Navn' in erindring
             and len(erindring['Navn'].split(',')) > 1 else None),
            'lastname':
            erindring['Efternavn'] if 'Efternavn' in erindring else
            (erindring['Navn'].split(',')[0].strip() if 'Navn' in erindring
             and len(erindring['Navn'].split(',')) > 0 else None),
            'sex':
            erindring.get('Køn'),
            'civilstatus':
            erindring.get('Civilstatus'),
            'yearOfBirth':
            jsonObj.get('Fødselsår'),
            "erindring_position":
            erindring.get('Stilling hovedperson'),
            "erindring_parent_position":
            erindring.get(u'Stilling forældre'),
            "erindring_spouse_position":
            erindring.get(u'Stilling ægtefælle'),
            "erindring_handwritten_typed":
            erindring.get(u'Håndskrevne/maskinskreven'),
            "erindring_description":
            erindring.get('Description'),
            "erindring_number":
            erindring['Erindringsnummer']
            if "Erindringsnummer" in erindring else None,
            "erindring_period":
            erindring.get('Periode'),
            "collected_year":
            erindring.get(u"Indsamlingsår"),
            "erindring_extent":
            erindring.get('Omfang'),
            "erindring_photos":
            'Foto' in erindring and erindring['Foto'],
            "erindring_keywords":
            erindring['Keywords'].split(',') if 'Keywords' in erindring
            and erindring['Keywords'] is not None else None,
            "erindring_document_text":
            erindring.get('Document Text'),
            "erindring_transcribed":
            "Transkriberet" in erindring and erindring['Transkriberet']
        })

        if len(self.documents) >= 100:
            self.solr.add(self.documents, commit=True)
            self.documents = []

    def wrapup(self):
        self.solr.add(self.documents, commit=True)
Exemple #21
0
 def send_rr_mr_cip(self, cippkt):
     """Encapsulate the CIP packet into a MultipleServicePacket to MessageRouter"""
     cipcm_msg = [cippkt]
     cippkt = CIP(path=CIP_Path(wordsize=2, path=b'\x20\x02\x24\x01'))
     cippkt /= CIP_MultipleServicePacket(packets=cipcm_msg)
     self.send_rr_cip(cippkt)
Exemple #22
0
class EfterretningerIndexer(IndexerBase):
    def __init__(self):
        super().__init__()
        self.commit_threshold = 100

    def collection_id(self):
        return 19

    def collection_info(self):
        return "Politiets efterretninger"

    def setup(self):
        self.log("Connecting to CIP... ")
        self.cip = CIP(Config['cumulus']['url'], Config['cumulus']['port'],
                       Config['cumulus']['user'],
                       Config['cumulus']['password'],
                       Config['cumulus']['location'])
        self.cip.load_layout(Config['cumulus']['layout'],
                             Config['cumulus']['layout'])
        self.log("OK.")

    def get_total(self):
        result = self.cip.search(
            Config['cumulus']['catalog'],
            view=Config['cumulus']['catalog'],
            querystring=
            "Samlingsnavn == 'Politiets Efterretninger' && Offentlig == true",
            maxreturned=1)
        return result['totalcount']

    def get_entries(self):
        return self.cip.searchall(
            Config['cumulus']['catalog'],
            view=Config['cumulus']['catalog'],
            querystring=
            "Samlingsnavn == 'Politiets Efterretninger' && Offentlig == true",
            chunk=50)

    def handle_entry(self, efterretning):
        jsonObj = {}
        jsonObj['id'] = "%d-%d" % (self.collection_id(), efterretning['ID'])
        jsonObj['org_id'] = "%d" % efterretning['ID']
        jsonObj['collection_id'] = self.collection_id()
        jsonObj['number'] = efterretning.get("Nummer")
        jsonObj['date'] = efterretning.get(u"Indsamlingsår").isoformat(
        ) if u"Indsamlingsår" in efterretning else None
        jsonObj['fileName'] = efterretning.get("Record Name")
        jsonObj['efterretning_type'] = efterretning.get(u"Description")

        self.documents.append({
            'id':
            "%d-%d" % (self.collection_id(), efterretning['ID']),
            'task_id':
            -1,
            'post_id':
            -1,
            'entry_id':
            -1,
            'user_id':
            -1,
            'user_name':
            ' ',
            'unit_id':
            -1,
            'page_id':
            -1,
            'jsonObj':
            json.dumps(jsonObj),
            'collection_id':
            self.collection_id(),
            'collection_info':
            self.collection_info(),
            'collected_year':
            efterretning.get(u"Indsamlingsår").year
            if u"Indsamlingsår" in efterretning else None,
            'efterretning_number':
            efterretning.get("Nummer"),
            'efterretning_date':
            efterretning.get(u"Indsamlingsår"),
            'efterretning_fileName':
            efterretning.get("Record Name"),
            'efterretning_type':
            efterretning.get(u"Description"),
            'erindring_document_text':
            efterretning.get('Document Text')
        })