Ejemplo n.º 1
0
    int IptcData::load(const byte* buf, long len)
    {
#ifdef DEBUG
        std::cerr << "IptcData::load, len = " << len << "\n";
#endif
        const byte* pRead = buf;
        iptcMetadata_.clear();

        uint16_t record = 0;
        uint16_t dataSet = 0;
        uint32_t sizeData = 0;
        byte extTest = 0;

        while (pRead + 3 < buf + len) {
            // First byte should be a marker. If it isn't, scan forward and skip
            // the chunk bytes present in some images. This deviates from the
            // standard, which advises to treat such cases as errors.
            if (*pRead++ != marker_) continue;
            record = *pRead++;
            dataSet = *pRead++;

            extTest = *pRead;
            if (extTest & 0x80) {
                // extended dataset
                uint16_t sizeOfSize = (getUShort(pRead, bigEndian) & 0x7FFF);
                if (sizeOfSize > 4) return 5;
                pRead += 2;
                sizeData = 0;
                for (; sizeOfSize > 0; --sizeOfSize) {
                    sizeData |= *pRead++ << (8 *(sizeOfSize-1));
                }
            }
            else {
                // standard dataset
                sizeData = getUShort(pRead, bigEndian);
                pRead += 2;
            }
            if (pRead + sizeData <= buf + len) {
                int rc = 0;
                if ((rc = readData(dataSet, record, pRead, sizeData)) != 0) {
#ifndef SUPPRESS_WARNINGS
                    std::cerr << "Warning: "
                              << "Failed to read IPTC dataset "
                              << IptcKey(dataSet, record)
                              << " (rc = " << rc << "); skipped.\n";
#endif
                }
            }
#ifndef SUPPRESS_WARNINGS
            else {
                std::cerr << "Warning: "
                          << "IPTC dataset " << IptcKey(dataSet, record)
                          << " has invalid size " << sizeData << "; skipped.\n";
            }
#endif
            pRead += sizeData;
        }

        return 0;
    } // IptcData::load
Ejemplo n.º 2
0
 void CiffDirectory::readDirectory(const byte* buf,
                                   uint32_t len,
                                   uint32_t start,
                                   ByteOrder byteOrder,
                                   int32_t /*shift*/)
 {
     uint32_t dataSize = getULong(buf + len - 4, byteOrder);
     uint32_t o = start + dataSize;
     if (o + 2 > len) throw Error(33);
     uint16_t count = getUShort(buf + o, byteOrder);
     o += 2;
     for (uint16_t i = 0; i < count; ++i) {
         if (o + 10 > len) throw Error(33);
         uint16_t tag = getUShort(buf + o, byteOrder);
         CiffComponent* p = 0;
         switch (CiffComponent::typeId(tag)) {
         case directory: p = new CiffDirectory; break;
         default: p = new CiffEntry; break;
         }
         p->setDir(this->tag());
         RawMetadata::AutoPtr m(p);
         m->read(buf, len, o, byteOrder);
         add(m);
         o += 10;
     }
 }  // CiffDirectory::readDirectory
Ejemplo n.º 3
0
isc_result_t
ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count,
	  int *rc) {
	const u_char *optr = ptr;

	for ((void)NULL; count > 0; count--) {
		int b, rdlength;

		b = dn_skipname(ptr, eom);
		if (b < 0)
			return ISC_R_INCOMPLETE;
		ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
		if (section != ns_s_qd) {
			if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
				return ISC_R_INCOMPLETE;
			ptr += NS_INT32SZ/*TTL*/;
			rdlength = getUShort(ptr);
			ptr += 2;
			ptr += rdlength/*RData*/;
		}
	}
	if (ptr > eom)
		return ISC_R_INCOMPLETE;
	if (rc)
		*rc = ptr - optr;
	return ISC_R_SUCCESS;
}
Ejemplo n.º 4
0
    // Todo: Generalised from JpegBase::locateIptcData without really understanding
    //       the format (in particular the header). So it remains to be confirmed
    //       if this also makes sense for psTag != Photoshop::iptc
    int Photoshop::locateIrb(const byte*     pPsData,
                             long            sizePsData,
                             uint16_t        psTag,
                             const byte**    record,
                             uint32_t *const sizeHdr,
                             uint32_t *const sizeData)
    {
        assert(record);
        assert(sizeHdr);
        assert(sizeData);
        // Used for error checking
        long position = 0;

        // Data should follow Photoshop format, if not exit
        while (   position <= sizePsData - 14
               && memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) {
            const byte *hrd = pPsData + position;
            position += 4;
            uint16_t type = getUShort(pPsData + position, bigEndian);
            position += 2;

            // Pascal string is padded to have an even size (including size byte)
            byte psSize = pPsData[position] + 1;
            psSize += (psSize & 1);
            position += psSize;
            if (position + 4 > sizePsData) {
#ifndef SUPPRESS_WARNINGS
                std::cerr << "Error: "
                          << "Invalid Photoshop IRB\n";
#endif
                return -2;
            }
            uint32_t dataSize = getULong(pPsData + position, bigEndian);
            position += 4;
            if (dataSize > static_cast<uint32_t>(sizePsData - position)) {
#ifndef SUPPRESS_WARNINGS
                std::cerr << "Error: "
                          << "Invalid Photoshop IRB data size "
                          << dataSize << "\n";
#endif
                return -2;
            }
#ifndef DEBUG
            if (   (dataSize & 1) 
                && position + dataSize == static_cast<uint32_t>(sizePsData)) {
                std::cerr << "Warning: "
                          << "Photoshop IRB data is not padded to even size\n";
            }
#endif
            if (type == psTag) {
                *sizeData = dataSize;
                *sizeHdr = psSize + 10;
                *record = hrd;
                return 0;
            }
            // Data size is also padded to be even
            position += dataSize + (dataSize & 1);
        }
        return 3;
    } // Photoshop::locateIrb
Ejemplo n.º 5
0
/**
 * Entry function which will process the assembled code and perform the required actions
 */
void processAssembledCode(char * assembled, unsigned int length, unsigned short numberSymbols,
		int coreId, int numberActiveCores, int baseHostPid) {
	stopInterpreter=0;
	currentSymbolEntries=0;
	localCoreId=coreId;
	numActiveCores=numberActiveCores;
	symbolTable=initialiseSymbolTable(numberSymbols);
	hostCoresBasePid=baseHostPid;
	unsigned int i;
	for (i=0;i<length;) {
		unsigned short command=getUShort(&assembled[i]);
		i+=sizeof(unsigned short);
		if (command == LET_TOKEN) i=handleLet(assembled, i);
		if (command == ARRAYSET_TOKEN) i=handleArraySet(assembled, i);
		if (command == DIMARRAY_TOKEN) i=handleDimArray(assembled, i, 0);
		if (command == DIMSHAREDARRAY_TOKEN) i=handleDimArray(assembled, i, 1);
		if (command == PRINT_TOKEN) i=handlePrint(assembled, i);
		if (command == STOP_TOKEN) return;
		if (command == SYNC_TOKEN) i=handleSync(assembled, i);
		if (command == IF_TOKEN) i=handleIf(assembled, i);
		if (command == IFELSE_TOKEN) i=handleIf(assembled, i);
		if (command == FOR_TOKEN) i=handleFor(assembled, i);
		if (command == GOTO_TOKEN) i=handleGoto(assembled, i);
		if (command == INPUT_TOKEN) i=handleInput(assembled, i);
		if (command == INPUT_STRING_TOKEN) i=handleInputWithString(assembled, i);
		if (command == SEND_TOKEN) i=handleSend(assembled, i);
		if (command == RECV_TOKEN) i=handleRecv(assembled, i);
		if (command == RECVTOARRAY_TOKEN) i=handleRecvToArray(assembled, i);
		if (command == SENDRECV_TOKEN) i=handleSendRecv(assembled, i);
		if (command == SENDRECVARRAY_TOKEN) i=handleSendRecvArray(assembled, i);
		if (command == BCAST_TOKEN) i=handleBcast(assembled, i);
		if (command == REDUCTION_TOKEN) i=handleReduction(assembled, i);
		if (stopInterpreter) return;
	}
}
Ejemplo n.º 6
0
static unsigned int handleLet(char * assembled, unsigned int currentPoint, unsigned int length, char restrictNoAlias, int threadId) {
#else
static unsigned int handleLet(char * assembled, unsigned int currentPoint, unsigned int length, char restrictNoAlias) {
#endif
    unsigned short varId=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
    struct symbol_node* variableSymbol=getVariableSymbol(varId, fnLevel[threadId], threadId, 1);
    struct value_defn value=getExpressionValue(assembled, &currentPoint, length, threadId);
    if (restrictNoAlias && getVariableSymbol(varId, fnLevel[threadId], threadId, 0)->state==ALIAS) return currentPoint;
#else
    struct symbol_node* variableSymbol=getVariableSymbol(varId, fnLevel, 1);
    struct value_defn value=getExpressionValue(assembled, &currentPoint, length);
    if (restrictNoAlias && getVariableSymbol(varId, fnLevel, 0)->state==ALIAS) return currentPoint;
#endif
    variableSymbol->value.type=value.type;
    variableSymbol->value.dtype=value.dtype;
    if (value.dtype == ARRAY) {
        cpy(variableSymbol->value.data, value.data, sizeof(char*));
    } else if (value.type == STRING_TYPE) {
        cpy(&variableSymbol->value.data, &value.data, sizeof(char*));
    } else {
        int currentAddress=getInt(variableSymbol->value.data);
        if (currentAddress == 0) {
            char * address=getStackMemory(sizeof(int), 0);
            cpy(variableSymbol->value.data, &address, sizeof(char*));
            cpy(address, value.data, sizeof(int));
        } else {
            setVariableValue(variableSymbol, value, -1);
        }
    }
    return currentPoint;
}
Ejemplo n.º 7
0
isc_result_t
ns_initparse(const u_char *msg, unsigned msglen, ns_msg *handle) {
	const u_char *eom = msg + msglen;
	int i;

	memset(handle, 0x5e, sizeof *handle);
	handle->_msg = msg;
	handle->_eom = eom;
	if (msg + NS_INT16SZ > eom)
		return ISC_R_INCOMPLETE;
	handle->_id = getUShort (msg);
	msg += 2;
	if (msg + NS_INT16SZ > eom)
		return ISC_R_INCOMPLETE;
	handle->_flags = getUShort (msg);
	msg += 2;
	for (i = 0; i < ns_s_max; i++) {
		if (msg + NS_INT16SZ > eom)
			return ISC_R_INCOMPLETE;
		handle->_counts[i] = getUShort (msg);
		msg += 2;
	}
	for (i = 0; i < ns_s_max; i++)
		if (handle->_counts[i] == 0)
			handle->_sections[i] = NULL;
		else {
			int b;
			isc_result_t status =
				ns_skiprr(msg, eom, (ns_sect)i,
					  handle->_counts[i], &b);

			if (status != ISC_R_SUCCESS)
				return STATUS;
			handle->_sections[i] = msg;
			msg += b;
		}
	if (msg != eom)
		return ISC_R_INCOMPLETE;
	setsection(handle, ns_s_max);
	return ISC_R_SUCCESS;
}
Ejemplo n.º 8
0
    int IptcData::load(const byte* buf, long len)
    {
        const byte* pRead = buf;
        iptcMetadata_.clear();

        uint16_t record = 0;
        uint16_t dataSet = 0;
        uint32_t sizeData = 0;
        byte extTest = 0;

        while (pRead + 3 < buf + len) {
            // First byte should be a marker. If it isn't, scan forward and skip
            // the chunk bytes present in some images. This deviates from the
            // standard, which advises to treat such cases as errors.
            if (*pRead++ != marker_) continue;
            record = *pRead++;
            dataSet = *pRead++;

            extTest = *pRead;
            if (extTest & 0x80) {
                // extended dataset
                uint16_t sizeOfSize = (getUShort(pRead, bigEndian) & 0x7FFF);
                if (sizeOfSize > 4) return 5;
                pRead += 2;
                sizeData = 0;
                for (; sizeOfSize > 0; --sizeOfSize) {
                    sizeData |= *pRead++ << (8 *(sizeOfSize-1));
                }
            }
            else {
                // standard dataset
                sizeData = getUShort(pRead, bigEndian);
                pRead += 2;
            }
            readData(dataSet, record, pRead, sizeData);
            pRead += sizeData;
        }

        return 0;
    } // IptcData::read
Ejemplo n.º 9
0
    int FujiMakerNote::readHeader(const byte* buf,
                                  long len, 
                                  ByteOrder byteOrder)
    {
        if (len < 12) return 1;

        header_.alloc(12);
        memcpy(header_.pData_, buf, header_.size_);
        // Read the offset relative to the start of the makernote from the header
        // Note: we ignore the byteOrder paramter
        adjOffset_ = getUShort(header_.pData_ + 8, byteOrder_);
        return 0;
    }
Ejemplo n.º 10
0
    int FujiMakerNote::readHeader(const byte* buf,
                                  long len,
                                  ByteOrder /*byteOrder*/)
    {
        if (len < 12) return 1;

        header_.alloc(12);
        std::memcpy(header_.pData_, buf, header_.size_);
        // Read offset to the IFD relative to the start of the makernote
        // from the header. Note that we ignore the byteOrder paramter
        start_ = getUShort(header_.pData_ + 8, byteOrder_);
        return 0;
    }
Ejemplo n.º 11
0
    int IptcData::read(const byte* buf, long len)
    {
        const byte* pRead = buf;
        iptcMetadata_.clear();

        int rc = 0;
        uint16_t record = 0;
        uint16_t dataSet = 0;
        uint32_t sizeData = 0;
        byte extTest = 0;

        while (pRead + 3 < buf + len) {
            if (*pRead++ != marker_) return 5;
            record = *pRead++;
            dataSet = *pRead++;
            
            extTest = *pRead;
            if (extTest & 0x80) {
                // extended dataset
                uint16_t sizeOfSize = (getUShort(pRead, bigEndian) & 0x7FFF);
                if (sizeOfSize > 4) return 5;
                pRead += 2;
                sizeData = 0;
                for (; sizeOfSize > 0; --sizeOfSize) {
                    sizeData |= *pRead++ << (8 *(sizeOfSize-1));
                }
            }
            else {
                // standard dataset
                sizeData = getUShort(pRead, bigEndian);
                pRead += 2;
            }
            rc = readData(dataSet, record, pRead, sizeData);
            if( rc ) return rc;
            pRead += sizeData;
        }

        return rc;
    } // IptcData::read
Ejemplo n.º 12
0
int TiffHeader::read(const byte* buf)
{
    if (buf[0] == 0x49 && buf[1] == 0x49) {
        byteOrder_ = littleEndian;
    }
    else if (buf[0] == 0x4d && buf[1] == 0x4d) {
        byteOrder_ = bigEndian;
    }
    else {
        return 1;
    }
    tag_ = getUShort(buf+2, byteOrder_);
    offset_ = getULong(buf+4, byteOrder_);
    return 0;
}
Ejemplo n.º 13
0
	void IptcData::printStructure(std::ostream& out, const byte* bytes,const size_t size,uint32_t depth)
	{
		uint32_t i     = 0 ;
		while  ( i < size-3 && bytes[i] != 0x1c ) i++;
		depth++;
		out << Internal::indent(depth) << "Record | DataSet | Name                     | Length | Data" << std::endl;
		while ( bytes[i] == 0x1c && i < size-3 ) {
			char buff[100];
			uint16_t record  = bytes[i+1];
			uint16_t dataset = bytes[i+2];
			uint16_t len     = getUShort(bytes+i+3,bigEndian);
			sprintf(buff,"  %6d | %7d | %-24s | %6d | ",record,dataset, Exiv2::IptcDataSets::dataSetName(dataset,record).c_str(), len);

			out << buff << Internal::binaryToString(bytes,(len>40?40:len),i+5) << (len>40?"...":"") << std::endl;
			i += 5 + len;
		}
		depth--;
	}
Ejemplo n.º 14
0
    bool TiffHeade2::read(const byte* pData, uint32_t size)
    {
        if (size < 8) return false;

        if (pData[0] == 0x49 && pData[1] == 0x49) {
            byteOrder_ = littleEndian;
        }
        else if (pData[0] == 0x4d && pData[1] == 0x4d) {
            byteOrder_ = bigEndian;
        }
        else {
            return false;
        }
        if (tag_ != getUShort(pData + 2, byteOrder_)) return false;
        offset_ = getULong(pData + 4, byteOrder_);

        return true;
    } // TiffHeade2::read
Ejemplo n.º 15
0
static unsigned int handleArraySet(char * assembled, unsigned int currentPoint, unsigned int length, int threadId) {
#else
static unsigned int handleArraySet(char * assembled, unsigned int currentPoint, unsigned int length) {
#endif
    unsigned short varId=getUShort(&assembled[currentPoint]);
    currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
    struct symbol_node* variableSymbol=getVariableSymbol(varId, fnLevel[threadId], threadId, 1);
    int targetIndex=getArrayAccessorIndex(variableSymbol, assembled, &currentPoint, length, threadId);
    struct value_defn value=getExpressionValue(assembled, &currentPoint, length, threadId);
#else
    struct symbol_node* variableSymbol=getVariableSymbol(varId, fnLevel, 1);
    int targetIndex=getArrayAccessorIndex(variableSymbol, assembled, &currentPoint, length);
    struct value_defn value=getExpressionValue(assembled, &currentPoint, length);
#endif
    setVariableValue(variableSymbol, value, targetIndex);
    return currentPoint;
}
Ejemplo n.º 16
0
bool OrfHeader::read(const byte* pData, uint32_t size)
{
    if (size < 8) return false;

    if (pData[0] == 0x49 && pData[1] == 0x49) {
        setByteOrder(littleEndian);
    }
    else if (pData[0] == 0x4d && pData[1] == 0x4d) {
        setByteOrder(bigEndian);
    }
    else {
        return false;
    }
    if (tag() != getUShort(pData + 2, byteOrder())) return false;
    setOffset(getULong(pData + 4, byteOrder()));
    if (offset() != 0x00000008) return false;

    return true;
} // OrfHeader::read
Ejemplo n.º 17
0
    // Todo: Generalised from JpegBase::locateIptcData without really understanding
    //       the format (in particular the header). So it remains to be confirmed
    //       if this also makes sense for psTag != Photoshop::iptc
    int Photoshop::locateIrb(const byte*     pPsData,
                             long            sizePsData,
                             uint16_t        psTag,
                             const byte**    record,
                             uint32_t *const sizeHdr,
                             uint32_t *const sizeData)
    {
        assert(record);
        assert(sizeHdr);
        assert(sizeData);
        // Used for error checking
        long position = 0;

        // Data should follow Photoshop format, if not exit
        while (   position <= sizePsData - 14
               && memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) {
            const byte *hrd = pPsData + position;
            position += 4;
            uint16_t type = getUShort(pPsData + position, bigEndian);
            position += 2;

            // Pascal string is padded to have an even size (including size byte)
            byte psSize = pPsData[position] + 1;
            psSize += (psSize & 1);
            position += psSize;
            if (position >= sizePsData) return -2;

            // Data is also padded to be even
            uint32_t dataSize = getULong(pPsData + position, bigEndian);
            position += 4;
            if (dataSize > static_cast<uint32_t>(sizePsData - position)) return -2;

            if (type == psTag) {
                *sizeData = dataSize;
                *sizeHdr = psSize + 10;
                *record = hrd;
                return 0;
            }
            position += dataSize + (dataSize & 1);
        }
        return 3;
    } // Photoshop::locateIrb
Ejemplo n.º 18
0
    bool Cr2Header::read(const byte* pData, uint32_t size)
    {
        if (size < 16) return false;

        if (pData[0] == 0x49 && pData[1] == 0x49) {
            setByteOrder(littleEndian);
        }
        else if (pData[0] == 0x4d && pData[1] == 0x4d) {
            setByteOrder(bigEndian);
        }
        else {
            return false;
        }
        if (tag() != getUShort(pData + 2, byteOrder())) return false;
        setOffset(getULong(pData + 4, byteOrder()));
        if (0 != memcmp(pData + 8, cr2sig_, 4)) return false;
        offset2_ = getULong(pData + 12, byteOrder());

        return true;
    } // Cr2Header::read
Ejemplo n.º 19
0
    bool OrfHeader::read(const byte* pData, uint32_t size)
    {
        if (size < 8) return false;

        if (pData[0] == 0x49 && pData[1] == 0x49) {
            setByteOrder(littleEndian);
        }
        else if (pData[0] == 0x4d && pData[1] == 0x4d) {
            setByteOrder(bigEndian);
        }
        else {
            return false;
        }
        uint16_t sig = getUShort(pData + 2, byteOrder());
        if (tag() != sig && 0x5352 != sig) return false; // #658: Added 0x5352 for SP-560UZ
        sig_ = sig;
        setOffset(getULong(pData + 4, byteOrder()));
        if (offset() != 0x00000008) return false;

        return true;
    } // OrfHeader::read
Ejemplo n.º 20
0
 void CiffComponent::read(const byte* buf,
                          uint32_t len,
                          uint32_t start,
                          ByteOrder byteOrder,
                          int32_t /*shift*/)
 {
     if (len < 10) throw Error(33);
     tag_ = getUShort(buf + start, byteOrder);
     switch (dataLocation()) {
     case valueData:
         size_ = getULong(buf + start + 2, byteOrder);
         offset_ = getULong(buf + start + 6, byteOrder);
         break;
     case directoryData:
         size_ = 8;
         offset_ = start + 2;
         break;
     case invalidDataLocId:
     case lastDataLocId:
         // empty
         break;
     }
     pData_ = buf + offset_;
 } // CiffComponent::read
Ejemplo n.º 21
0
/*
 * Format the specified option so that a human can easily read it.
 */
char *
pretty_print_option(unsigned int code, unsigned char *data, int len,
    int emit_commas, int emit_quotes)
{
	static char optbuf[32768]; /* XXX */
	int hunksize = 0, numhunk = -1, numelem = 0;
	char fmtbuf[32], *op = optbuf;
	int i, j, k, opleft = sizeof(optbuf);
	unsigned char *dp = data;
	struct in_addr foo;
	char comma;

	/* Code should be between 0 and 255. */
	if (code > 255)
		error("pretty_print_option: bad code %d", code);

	if (emit_commas)
		comma = ',';
	else
		comma = ' ';

	/* Figure out the size of the data. */
	for (i = 0; dhcp_options[code].format[i]; i++) {
		if (!numhunk) {
			warning("%s: Excess information in format string: %s",
			    dhcp_options[code].name,
			    &(dhcp_options[code].format[i]));
			break;
		}
		numelem++;
		fmtbuf[i] = dhcp_options[code].format[i];
		switch (dhcp_options[code].format[i]) {
		case 'A':
			--numelem;
			fmtbuf[i] = 0;
			numhunk = 0;
			break;
		case 'X':
			for (k = 0; k < len; k++)
				if (!isascii(data[k]) ||
				    !isprint(data[k]))
					break;
			if (k == len) {
				fmtbuf[i] = 't';
				numhunk = -2;
			} else {
				fmtbuf[i] = 'x';
				hunksize++;
				comma = ':';
				numhunk = 0;
			}
			fmtbuf[i + 1] = 0;
			break;
		case 't':
			fmtbuf[i] = 't';
			fmtbuf[i + 1] = 0;
			numhunk = -2;
			break;
		case 'I':
		case 'l':
		case 'L':
			hunksize += 4;
			break;
		case 's':
		case 'S':
			hunksize += 2;
			break;
		case 'b':
		case 'B':
		case 'f':
			hunksize++;
			break;
		case 'e':
			break;
		default:
			warning("%s: garbage in format string: %s",
			    dhcp_options[code].name,
			    &(dhcp_options[code].format[i]));
			break;
		}
	}

	/* Check for too few bytes... */
	if (hunksize > len) {
		warning("%s: expecting at least %d bytes; got %d",
		    dhcp_options[code].name, hunksize, len);
		return ("<error>");
	}
	/* Check for too many bytes... */
	if (numhunk == -1 && hunksize < len)
		warning("%s: %d extra bytes",
		    dhcp_options[code].name, len - hunksize);

	/* If this is an array, compute its size. */
	if (!numhunk)
		numhunk = len / hunksize;
	/* See if we got an exact number of hunks. */
	if (numhunk > 0 && numhunk * hunksize < len)
		warning("%s: %d extra bytes at end of array",
		    dhcp_options[code].name, len - numhunk * hunksize);

	/* A one-hunk array prints the same as a single hunk. */
	if (numhunk < 0)
		numhunk = 1;

	/* Cycle through the array (or hunk) printing the data. */
	for (i = 0; i < numhunk; i++) {
		for (j = 0; j < numelem; j++) {
			int opcount;
			switch (fmtbuf[j]) {
			case 't':
				if (emit_quotes) {
					*op++ = '"';
					opleft--;
				}
				for (; dp < data + len; dp++) {
					if (!isascii(*dp) ||
					    !isprint(*dp)) {
						if (dp + 1 != data + len ||
						    *dp != 0) {
							snprintf(op, opleft,
							    "\\%03o", *dp);
							op += 4;
							opleft -= 4;
						}
					} else if (*dp == '"' ||
					    *dp == '\'' ||
					    *dp == '$' ||
					    *dp == '`' ||
					    *dp == '\\') {
						*op++ = '\\';
						*op++ = *dp;
						opleft -= 2;
					} else {
						*op++ = *dp;
						opleft--;
					}
				}
				if (emit_quotes) {
					*op++ = '"';
					opleft--;
				}

				*op = 0;
				break;
			case 'I':
				foo.s_addr = htonl(getULong(dp));
				opcount = strlcpy(op, inet_ntoa(foo), opleft);
				if (opcount >= opleft)
					goto toobig;
				opleft -= opcount;
				dp += 4;
				break;
			case 'l':
				opcount = snprintf(op, opleft, "%ld",
				    (long)getLong(dp));
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				dp += 4;
				break;
			case 'L':
				opcount = snprintf(op, opleft, "%ld",
				    (unsigned long)getULong(dp));
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				dp += 4;
				break;
			case 's':
				opcount = snprintf(op, opleft, "%d",
				    getShort(dp));
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				dp += 2;
				break;
			case 'S':
				opcount = snprintf(op, opleft, "%d",
				    getUShort(dp));
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				dp += 2;
				break;
			case 'b':
				opcount = snprintf(op, opleft, "%d",
				    *(char *)dp++);
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				break;
			case 'B':
				opcount = snprintf(op, opleft, "%d", *dp++);
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				break;
			case 'x':
				opcount = snprintf(op, opleft, "%x", *dp++);
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				break;
			case 'f':
				opcount = strlcpy(op,
				    *dp++ ? "true" : "false", opleft);
				if (opcount >= opleft)
					goto toobig;
				opleft -= opcount;
				break;
			default:
				warning("Unexpected format code %c", fmtbuf[j]);
			}
			op += strlen(op);
			opleft -= strlen(op);
			if (opleft < 1)
				goto toobig;
			if (j + 1 < numelem && comma != ':') {
				*op++ = ' ';
				opleft--;
			}
		}
		if (i + 1 < numhunk) {
			*op++ = comma;
			opleft--;
		}
		if (opleft < 1)
			goto toobig;

	}
	return (optbuf);
 toobig:
	warning("dhcp option too large");
	return ("<error>");
}
Ejemplo n.º 22
0
/*
 * cons options into a big buffer, and then split them out into the
 * three separate buffers if needed.  This allows us to cons up a set of
 * vendor options using the same routine.
 */
int
cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
    int mms, struct tree_cache **options,
    int overload, /* Overload flags that may be set. */
    int terminate, int bootpp, u_int8_t *prl, int prl_len)
{
	unsigned char priority_list[300], buffer[4096];
	int priority_len, main_buffer_size, mainbufix, bufix;
	int option_size, length;

	/*
	 * If the client has provided a maximum DHCP message size, use
	 * that; otherwise, if it's BOOTP, only 64 bytes; otherwise use
	 * up to the minimum IP MTU size (576 bytes).
	 *
	 * XXX if a BOOTP client specifies a max message size, we will
	 * honor it.
	 */
	if (!mms &&
	    inpacket &&
	    inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data &&
	    (inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].len >=
	    sizeof(u_int16_t)))
		mms = getUShort(
		    inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data);

	if (mms)
		main_buffer_size = mms - DHCP_FIXED_LEN;
	else if (bootpp)
		main_buffer_size = 64;
	else
		main_buffer_size = 576 - DHCP_FIXED_LEN;

	if (main_buffer_size > sizeof(buffer))
		main_buffer_size = sizeof(buffer);

	/* Preload the option priority list with mandatory options. */
	priority_len = 0;
	priority_list[priority_len++] = DHO_DHCP_MESSAGE_TYPE;
	priority_list[priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
	priority_list[priority_len++] = DHO_DHCP_LEASE_TIME;
	priority_list[priority_len++] = DHO_DHCP_MESSAGE;

	/*
	 * If the client has provided a list of options that it wishes
	 * returned, use it to prioritize.  Otherwise, prioritize based
	 * on the default priority list.
	 */
	if (inpacket &&
	    inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
		int prlen =
		    inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].len;
		if (prlen + priority_len > sizeof(priority_list))
			prlen = sizeof(priority_list) - priority_len;

		memcpy(&priority_list[priority_len],
		    inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data,
		    prlen);
		priority_len += prlen;
		prl = priority_list;
	} else if (prl) {
		if (prl_len + priority_len > sizeof(priority_list))
			prl_len = sizeof(priority_list) - priority_len;

		memcpy(&priority_list[priority_len], prl, prl_len);
		priority_len += prl_len;
		prl = priority_list;
	} else {
		memcpy(&priority_list[priority_len],
		    dhcp_option_default_priority_list,
		    sizeof_dhcp_option_default_priority_list);
		priority_len += sizeof_dhcp_option_default_priority_list;
	}

	/* Copy the options into the big buffer... */
	option_size = store_options(
	    buffer,
	    (main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0) +
		((overload & 2) ? DHCP_SNAME_LEN : 0)),
	    options, priority_list, priority_len, main_buffer_size,
	    (main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)),
	    terminate);

	/* Put the cookie up front... */
	memcpy(outpacket->options, DHCP_OPTIONS_COOKIE, 4);
	mainbufix = 4;

	/*
	 * If we're going to have to overload, store the overload option
	 * at the beginning.  If we can, though, just store the whole
	 * thing in the packet's option buffer and leave it at that.
	 */
	if (option_size <= main_buffer_size - mainbufix) {
		memcpy(&outpacket->options[mainbufix],
		    buffer, option_size);
		mainbufix += option_size;
		if (mainbufix < main_buffer_size)
			outpacket->options[mainbufix++] = DHO_END;
		length = DHCP_FIXED_NON_UDP + mainbufix;
	} else {
		outpacket->options[mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
		outpacket->options[mainbufix++] = 1;
		if (option_size >
		    main_buffer_size - mainbufix + DHCP_FILE_LEN)
			outpacket->options[mainbufix++] = 3;
		else
			outpacket->options[mainbufix++] = 1;

		memcpy(&outpacket->options[mainbufix],
		    buffer, main_buffer_size - mainbufix);
		bufix = main_buffer_size - mainbufix;
		length = DHCP_FIXED_NON_UDP + mainbufix;
		if (overload & 1) {
			if (option_size - bufix <= DHCP_FILE_LEN) {
				memcpy(outpacket->file,
				    &buffer[bufix], option_size - bufix);
				mainbufix = option_size - bufix;
				if (mainbufix < DHCP_FILE_LEN)
					outpacket->file[mainbufix++] = (char)DHO_END;
				while (mainbufix < DHCP_FILE_LEN)
					outpacket->file[mainbufix++] = (char)DHO_PAD;
			} else {
				memcpy(outpacket->file,
				    &buffer[bufix], DHCP_FILE_LEN);
				bufix += DHCP_FILE_LEN;
			}
		}
		if ((overload & 2) && option_size < bufix) {
			memcpy(outpacket->sname,
			    &buffer[bufix], option_size - bufix);

			mainbufix = option_size - bufix;
			if (mainbufix < DHCP_SNAME_LEN)
				outpacket->file[mainbufix++] = (char)DHO_END;
			while (mainbufix < DHCP_SNAME_LEN)
				outpacket->file[mainbufix++] = (char)DHO_PAD;
		}
	}
	return (length);
}
Ejemplo n.º 23
0
static QString getEnglishName(const uchar *table, quint32 bytes)
{
    QString i18n_name;
    enum {
        NameRecordSize = 12,
        FamilyId = 1,
        MS_LangIdEnglish = 0x009
    };

    // get the name table
    quint16 count;
    quint16 string_offset;
    const unsigned char *names;

    int microsoft_id = -1;
    int apple_id = -1;
    int unicode_id = -1;

    if(getUShort(table) != 0)
        goto error;

    count = getUShort(table+2);
    string_offset = getUShort(table+4);
    names = table + 6;

    if(string_offset >= bytes || 6 + count*NameRecordSize > string_offset)
        goto error;

    for(int i = 0; i < count; ++i) {
        // search for the correct name entry

        quint16 platform_id = getUShort(names + i*NameRecordSize);
        quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize);
        quint16 language_id = getUShort(names + 4 + i*NameRecordSize);
        quint16 name_id = getUShort(names + 6 + i*NameRecordSize);

        if(name_id != FamilyId)
            continue;

        enum {
            PlatformId_Unicode = 0,
            PlatformId_Apple = 1,
            PlatformId_Microsoft = 3
        };

        quint16 length = getUShort(names + 8 + i*NameRecordSize);
        quint16 offset = getUShort(names + 10 + i*NameRecordSize);
        if(DWORD(string_offset + offset + length) >= bytes)
            continue;

        if ((platform_id == PlatformId_Microsoft
            && (encoding_id == 0 || encoding_id == 1))
            && (language_id & 0x3ff) == MS_LangIdEnglish
            && microsoft_id == -1)
            microsoft_id = i;
            // not sure if encoding id 4 for Unicode is utf16 or ucs4...
        else if(platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1)
            unicode_id = i;
        else if(platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0)
            apple_id = i;
    }
    {
        bool unicode = false;
        int id = -1;
        if(microsoft_id != -1) {
            id = microsoft_id;
            unicode = true;
        } else if(apple_id != -1) {
            id = apple_id;
            unicode = false;
        } else if (unicode_id != -1) {
            id = unicode_id;
            unicode = true;
        }
        if(id != -1) {
            quint16 length = getUShort(names + 8 + id*NameRecordSize);
            quint16 offset = getUShort(names + 10 + id*NameRecordSize);
            if(unicode) {
                // utf16

                length /= 2;
                i18n_name.resize(length);
                QChar *uc = (QChar *) i18n_name.unicode();
                const unsigned char *string = table + string_offset + offset;
                for(int i = 0; i < length; ++i)
                    uc[i] = getUShort(string + 2*i);
            } else {
                // Apple Roman

                i18n_name.resize(length);
                QChar *uc = (QChar *) i18n_name.unicode();
                const unsigned char *string = table + string_offset + offset;
                for(int i = 0; i < length; ++i)
                    uc[i] = QLatin1Char(string[i]);
            }
        }
    }
  error:
    //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data());
    return i18n_name;
}
Ejemplo n.º 24
0
    void JpegBase::doWriteMetadata(BasicIo& outIo)
    {
        if (!io_->isopen()) throw Error(20);
        if (!outIo.isopen()) throw Error(21);

        // Ensure that this is the correct image type
        if (!isThisType(*io_, true)) {
            if (io_->error() || io_->eof()) throw Error(20);
            throw Error(22);
        }

        const long bufMinSize = 16;
        long bufRead = 0;
        DataBuf buf(bufMinSize);
        const long seek = io_->tell();
        int count = 0;
        int search = 0;
        int insertPos = 0;
        int skipApp1Exif = -1;
        int skipApp13Ps3 = -1;
        int skipCom = -1;
        DataBuf psData;

        // Write image header
        if (writeHeader(outIo)) throw Error(21);

        // Read section marker
        int marker = advanceToMarker();
        if (marker < 0) throw Error(22);

        // First find segments of interest. Normally app0 is first and we want
        // to insert after it. But if app0 comes after com, app1 and app13 then
        // don't bother.
        while (marker != sos_ && marker != eoi_ && search < 3) {
            // Read size and signature (ok if this hits EOF)
            bufRead = io_->read(buf.pData_, bufMinSize);
            if (io_->error()) throw Error(20);
            uint16_t size = getUShort(buf.pData_, bigEndian);

            if (marker == app0_) {
                if (size < 2) throw Error(22);
                insertPos = count + 1;
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            else if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
                if (size < 8) throw Error(22);
                skipApp1Exif = count;
                ++search;
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            else if (marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) {
                if (size < 16) throw Error(22);
                skipApp13Ps3 = count;
                ++search;
                // needed if bufMinSize!=16: io_->seek(16-bufRead, BasicIo::cur);
                psData.alloc(size - 16);
                // Load PS data now to allow reinsertion at any point
                io_->read(psData.pData_, psData.size_);
                if (io_->error() || io_->eof()) throw Error(20);
            }
            else if (marker == com_ && skipCom == -1) {
                if (size < 2) throw Error(22);
                // Jpegs can have multiple comments, but for now only handle
                // the first one (most jpegs only have one anyway).
                skipCom = count;
                ++search;
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            else {
                if (size < 2) throw Error(22);
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            marker = advanceToMarker();
            if (marker < 0) throw Error(22);
            ++count;
        }

        if (exifData_.count() > 0) ++search;
        if (iptcData_.count() > 0) ++search;
        if (!comment_.empty()) ++search;

        io_->seek(seek, BasicIo::beg);
        count = 0;
        marker = advanceToMarker();
        if (marker < 0) throw Error(22);

        // To simplify this a bit, new segments are inserts at either the start
        // or right after app0. This is standard in most jpegs, but has the
        // potential to change segment ordering (which is allowed).
        // Segments are erased if there is no assigned metadata.
        while (marker != sos_ && search > 0) {
            // Read size and signature (ok if this hits EOF)
            bufRead = io_->read(buf.pData_, bufMinSize);
            if (io_->error()) throw Error(20);
            // Careful, this can be a meaningless number for empty
            // images with only an eoi_ marker
            uint16_t size = getUShort(buf.pData_, bigEndian);

            if (insertPos == count) {
                byte tmpBuf[18];
                if (!comment_.empty()) {
                    // Write COM marker, size of comment, and string
                    tmpBuf[0] = 0xff;
                    tmpBuf[1] = com_;

                    if (comment_.length() + 3 > 0xffff) throw Error(37, "JPEG comment");
                    us2Data(tmpBuf + 2, static_cast<uint16_t>(comment_.length() + 3), bigEndian);

                    if (outIo.write(tmpBuf, 4) != 4) throw Error(21);
                    if (outIo.write((byte*)comment_.data(), (long)comment_.length())
                        != (long)comment_.length()) throw Error(21);
                    if (outIo.putb(0)==EOF) throw Error(21);
                    if (outIo.error()) throw Error(21);
                    --search;
                }
                if (exifData_.count() > 0) {
                    DataBuf rawExif = exifData_.copy();
                    if (rawExif.size_ > 0) {
                        // Write APP1 marker, size of APP1 field, Exif id and Exif data
                        tmpBuf[0] = 0xff;
                        tmpBuf[1] = app1_;

                        if (rawExif.size_ + 8 > 0xffff) throw Error(37, "Exif");
                        us2Data(tmpBuf + 2, static_cast<uint16_t>(rawExif.size_ + 8), bigEndian);
                        memcpy(tmpBuf + 4, exifId_, 6);
                        if (outIo.write(tmpBuf, 10) != 10) throw Error(21);

                        // Write new Exif data buffer
                        if (   outIo.write(rawExif.pData_, rawExif.size_)
                               != rawExif.size_) throw Error(21);
                        if (outIo.error()) throw Error(21);
                        --search;
                    }
                }
                if (psData.size_ > 0 || iptcData_.count() > 0) {
                    // Set the new IPTC IRB, keeps existing IRBs but removes the
                    // IPTC block if there is no new IPTC data to write
                    DataBuf newPsData = Photoshop::setIptcIrb(psData.pData_,
                                                              psData.size_,
                                                              iptcData_);
                    if (newPsData.size_ > 0) {
                        // Write APP13 marker, new size, and ps3Id
                        tmpBuf[0] = 0xff;
                        tmpBuf[1] = app13_;

                        if (newPsData.size_ + 16 > 0xffff) throw Error(37, "IPTC");
                        us2Data(tmpBuf + 2, static_cast<uint16_t>(newPsData.size_ + 16), bigEndian);
                        memcpy(tmpBuf + 4, Photoshop::ps3Id_, 14);
                        if (outIo.write(tmpBuf, 18) != 18) throw Error(21);
                        if (outIo.error()) throw Error(21);

                        // Write new Photoshop IRB data buffer
                        if (   outIo.write(newPsData.pData_, newPsData.size_)
                            != newPsData.size_) throw Error(21);
                        if (outIo.error()) throw Error(21);
                    }
                    if (iptcData_.count() > 0) {
                        --search;
                    }
                }
            }
            if (marker == eoi_) {
                break;
            }
            else if (skipApp1Exif==count || skipApp13Ps3==count || skipCom==count) {
                --search;
                io_->seek(size-bufRead, BasicIo::cur);
            }
            else {
                if (size < 2) throw Error(22);
                buf.alloc(size+2);
                io_->seek(-bufRead-2, BasicIo::cur);
                io_->read(buf.pData_, size+2);
                if (io_->error() || io_->eof()) throw Error(20);
                if (outIo.write(buf.pData_, size+2) != size+2) throw Error(21);
                if (outIo.error()) throw Error(21);
            }

            // Next marker
            marker = advanceToMarker();
            if (marker < 0) throw Error(22);
            ++count;
        }

        // Copy rest of the Io
        io_->seek(-2, BasicIo::cur);
        buf.alloc(4096);
        long readSize = 0;
        while ((readSize=io_->read(buf.pData_, buf.size_))) {
            if (outIo.write(buf.pData_, readSize) != readSize) throw Error(21);
        }
        if (outIo.error()) throw Error(21);

    } // JpegBase::doWriteMetadata
Ejemplo n.º 25
0
unsigned short PvObject::getUShort() const
{
    std::string key = PyPvDataUtility::getValueOrSingleFieldName(pvStructurePtr);
    return getUShort(key);
}
Ejemplo n.º 26
0
 inline uint16_t getValue(const byte* buf, ByteOrder byteOrder)
 {
     return getUShort(buf, byteOrder);
 }
Ejemplo n.º 27
0
    void JpegBase::doWriteMetadata(BasicIo& outIo)
    {
        if (!io_->isopen()) throw Error(20);
        if (!outIo.isopen()) throw Error(21);

        // Ensure that this is the correct image type
        if (!isThisType(*io_, true)) {
            if (io_->error() || io_->eof()) throw Error(20);
            throw Error(22);
        }

        const long bufMinSize = 36;
        long bufRead = 0;
        DataBuf buf(bufMinSize);
        const long seek = io_->tell();
        int count = 0;
        int search = 0;
        int insertPos = 0;
        int comPos = 0;
        int skipApp1Exif = -1;
        int skipApp1Xmp = -1;
        int skipApp13Ps3 = -1;
        int skipCom = -1;
        DataBuf psData;
        DataBuf rawExif;

        // Write image header
        if (writeHeader(outIo)) throw Error(21);

        // Read section marker
        int marker = advanceToMarker();
        if (marker < 0) throw Error(22);

        // First find segments of interest. Normally app0 is first and we want
        // to insert after it. But if app0 comes after com, app1 and app13 then
        // don't bother.
        while (marker != sos_ && marker != eoi_ && search < 5) {
            // Read size and signature (ok if this hits EOF)
            bufRead = io_->read(buf.pData_, bufMinSize);
            if (io_->error()) throw Error(20);
            uint16_t size = getUShort(buf.pData_, bigEndian);

            if (marker == app0_) {
                if (size < 2) throw Error(22);
                insertPos = count + 1;
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            else if (   skipApp1Exif == -1
                     && marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
                if (size < 8) throw Error(22);
                skipApp1Exif = count;
                ++search;
                // Seek to beginning and read the current Exif data
                io_->seek(8 - bufRead, BasicIo::cur);
                rawExif.alloc(size - 8);
                io_->read(rawExif.pData_, rawExif.size_);
                if (io_->error() || io_->eof()) throw Error(22);
            }
            else if (marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) {
                if (size < 31) throw Error(22);
                skipApp1Xmp = count;
                ++search;
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            else if (marker == app13_ && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) {
#ifdef DEBUG
                std::cerr << "Found APP13 Photoshop PS3 segment\n";
#endif
                if (size < 16) throw Error(22);
                skipApp13Ps3 = count;
                ++search;
                io_->seek(16 - bufRead, BasicIo::cur);
                psData.alloc(size - 16);
                // Load PS data now to allow reinsertion at any point
                io_->read(psData.pData_, size - 16);
                if (io_->error() || io_->eof()) throw Error(20);
            }
            else if (marker == com_ && skipCom == -1) {
                if (size < 2) throw Error(22);
                // Jpegs can have multiple comments, but for now only handle
                // the first one (most jpegs only have one anyway).
                skipCom = count;
                ++search;
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            else {
                if (size < 2) throw Error(22);
                if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
            }
            // As in jpeg-6b/wrjpgcom.c:
            // We will insert the new comment marker just before SOFn.
            // This (a) causes the new comment to appear after, rather than before,
            // existing comments; and (b) ensures that comments come after any JFIF
            // or JFXX markers, as required by the JFIF specification.
            if (   comPos == 0
                && (   marker == sof0_
                    || marker == sof1_
                    || marker == sof2_
                    || marker == sof3_
                    || marker == sof5_
                    || marker == sof6_
                    || marker == sof7_
                    || marker == sof9_
                    || marker == sof10_
                    || marker == sof11_
                    || marker == sof13_
                    || marker == sof14_
                    || marker == sof15_)) {
                comPos = count;
                ++search;
            }
            marker = advanceToMarker();
            if (marker < 0) throw Error(22);
            ++count;
        }
        if (comPos == 0) {
            if (marker == eoi_) comPos = count;
            else comPos = insertPos;
            ++search;
        }
        if (exifData_.count() > 0) ++search;
        if (writeXmpFromPacket() == false && xmpData_.count() > 0) ++search;
        if (writeXmpFromPacket() == true && xmpPacket_.size() > 0) ++search;
        if (iptcData_.count() > 0) ++search;
        if (!comment_.empty()) ++search;

        io_->seek(seek, BasicIo::beg);
        count = 0;
        marker = advanceToMarker();
        if (marker < 0) throw Error(22);

        // To simplify this a bit, new segments are inserts at either the start
        // or right after app0. This is standard in most jpegs, but has the
        // potential to change segment ordering (which is allowed).
        // Segments are erased if there is no assigned metadata.
        while (marker != sos_ && search > 0) {
            // Read size and signature (ok if this hits EOF)
            bufRead = io_->read(buf.pData_, bufMinSize);
            if (io_->error()) throw Error(20);
            // Careful, this can be a meaningless number for empty
            // images with only an eoi_ marker
            uint16_t size = getUShort(buf.pData_, bigEndian);

            if (insertPos == count) {
                byte tmpBuf[64];
                // Write Exif data first so that - if there is no app0 - we
                // create "Exif images" according to the Exif standard.
                if (exifData_.count() > 0) {
                    Blob blob;
                    ByteOrder bo = byteOrder();
                    if (bo == invalidByteOrder) {
                        bo = littleEndian;
                        setByteOrder(bo);
                    }
                    WriteMethod wm = ExifParser::encode(blob,
                                                        rawExif.pData_,
                                                        rawExif.size_,
                                                        bo,
                                                        exifData_);
                    const byte* pExifData = rawExif.pData_;
                    uint32_t exifSize = rawExif.size_;
                    if (wm == wmIntrusive) {
                        pExifData = blob.size() > 0 ? &blob[0] : 0;
                        exifSize = static_cast<uint32_t>(blob.size());
                    }
                    if (exifSize > 0) {
                        // Write APP1 marker, size of APP1 field, Exif id and Exif data
                        tmpBuf[0] = 0xff;
                        tmpBuf[1] = app1_;

                        if (exifSize + 8 > 0xffff) throw Error(37, "Exif");
                        us2Data(tmpBuf + 2, static_cast<uint16_t>(exifSize + 8), bigEndian);
                        std::memcpy(tmpBuf + 4, exifId_, 6);
                        if (outIo.write(tmpBuf, 10) != 10) throw Error(21);

                        // Write new Exif data buffer
                        if (   outIo.write(pExifData, exifSize)
                            != static_cast<long>(exifSize)) throw Error(21);
                        if (outIo.error()) throw Error(21);
                        --search;
                    }
                }
                if (writeXmpFromPacket() == false) {
                    if (XmpParser::encode(xmpPacket_, xmpData_) > 1) {
#ifndef SUPPRESS_WARNINGS
                        std::cerr << "Error: Failed to encode XMP metadata.\n";
#endif
                    }
                }
                if (xmpPacket_.size() > 0) {
                    // Write APP1 marker, size of APP1 field, XMP id and XMP packet
                    tmpBuf[0] = 0xff;
                    tmpBuf[1] = app1_;

                    if (xmpPacket_.size() + 31 > 0xffff) throw Error(37, "XMP");
                    us2Data(tmpBuf + 2, static_cast<uint16_t>(xmpPacket_.size() + 31), bigEndian);
                    std::memcpy(tmpBuf + 4, xmpId_, 29);
                    if (outIo.write(tmpBuf, 33) != 33) throw Error(21);

                    // Write new XMP packet
                    if (   outIo.write(reinterpret_cast<const byte*>(xmpPacket_.data()), static_cast<long>(xmpPacket_.size()))
                        != static_cast<long>(xmpPacket_.size())) throw Error(21);
                    if (outIo.error()) throw Error(21);
                    --search;
                }
                if (psData.size_ > 0 || iptcData_.count() > 0) {
                    // Set the new IPTC IRB, keeps existing IRBs but removes the
                    // IPTC block if there is no new IPTC data to write
                    DataBuf newPsData = Photoshop::setIptcIrb(psData.pData_,
                                                              psData.size_,
                                                              iptcData_);
                    if (newPsData.size_ > 0) {
                        // Write APP13 marker, new size, and ps3Id
                        tmpBuf[0] = 0xff;
                        tmpBuf[1] = app13_;

                        if (newPsData.size_ + 16 > 0xffff) throw Error(37, "IPTC");
                        us2Data(tmpBuf + 2, static_cast<uint16_t>(newPsData.size_ + 16), bigEndian);
                        std::memcpy(tmpBuf + 4, Photoshop::ps3Id_, 14);
                        if (outIo.write(tmpBuf, 18) != 18) throw Error(21);
                        if (outIo.error()) throw Error(21);

                        // Write new Photoshop IRB data buffer
                        if (   outIo.write(newPsData.pData_, newPsData.size_)
                            != newPsData.size_) throw Error(21);
                        if (outIo.error()) throw Error(21);
                    }
                    if (iptcData_.count() > 0) {
                        --search;
                    }
                }
            }
            if (comPos == count) {
                if (!comment_.empty()) {
                    byte tmpBuf[4];
                    // Write COM marker, size of comment, and string
                    tmpBuf[0] = 0xff;
                    tmpBuf[1] = com_;

                    if (comment_.length() + 3 > 0xffff) throw Error(37, "JPEG comment");
                    us2Data(tmpBuf + 2, static_cast<uint16_t>(comment_.length() + 3), bigEndian);

                    if (outIo.write(tmpBuf, 4) != 4) throw Error(21);
                    if (outIo.write((byte*)comment_.data(), (long)comment_.length())
                        != (long)comment_.length()) throw Error(21);
                    if (outIo.putb(0)==EOF) throw Error(21);
                    if (outIo.error()) throw Error(21);
                    --search;
                }
                --search;
            }
            if (marker == eoi_) {
                break;
            }
            else if (   skipApp1Exif == count
                     || skipApp1Xmp  == count
                     || skipApp13Ps3 == count
                     || skipCom      == count) {
                --search;
                io_->seek(size-bufRead, BasicIo::cur);
            }
            else {
                if (size < 2) throw Error(22);
                buf.alloc(size+2);
                io_->seek(-bufRead-2, BasicIo::cur);
                io_->read(buf.pData_, size+2);
                if (io_->error() || io_->eof()) throw Error(20);
                if (outIo.write(buf.pData_, size+2) != size+2) throw Error(21);
                if (outIo.error()) throw Error(21);
            }

            // Next marker
            marker = advanceToMarker();
            if (marker < 0) throw Error(22);
            ++count;
        }

        // Copy rest of the Io
        io_->seek(-2, BasicIo::cur);
        buf.alloc(4096);
        long readSize = 0;
        while ((readSize=io_->read(buf.pData_, buf.size_))) {
            if (outIo.write(buf.pData_, readSize) != readSize) throw Error(21);
        }
        if (outIo.error()) throw Error(21);

    } // JpegBase::doWriteMetadata
Ejemplo n.º 28
0
    void JpegBase::readMetadata()
    {
        int rc = 0; // Todo: this should be the return value

        if (io_->open() != 0) throw Error(9, io_->path(), strError());
        IoCloser closer(*io_);
        // Ensure that this is the correct image type
        if (!isThisType(*io_, true)) {
            if (io_->error() || io_->eof()) throw Error(14);
            throw Error(15);
        }
        clearMetadata();
        int search = 5;
        const long bufMinSize = 36;
        long bufRead = 0;
        DataBuf buf(bufMinSize);
        Blob iptcBlob;
        bool foundPsData = false;
        bool foundExifData = false;

        // Read section marker
        int marker = advanceToMarker();
        if (marker < 0) throw Error(15);

        while (marker != sos_ && marker != eoi_ && search > 0) {
            // Read size and signature (ok if this hits EOF)
            std::memset(buf.pData_, 0x0, buf.size_);
            bufRead = io_->read(buf.pData_, bufMinSize);
            if (io_->error()) throw Error(14);
            if (bufRead < 2) throw Error(15);
            uint16_t size = getUShort(buf.pData_, bigEndian);

            if (foundPsData && marker != app13_) {
                // For IPTC, decrement search only after all app13 segments are
                // loaded, assuming they all appear in sequence. But decode IPTC
                // data after the loop, in case an app13 is the last segment
                // before sos or eoi.
                foundPsData = false;
                if (--search == 0) break;
            }

            if (   !foundExifData
                && marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
                if (size < 8) {
                    rc = 1;
                    break;
                }
                // Seek to beginning and read the Exif data
                io_->seek(8 - bufRead, BasicIo::cur);
                DataBuf rawExif(size - 8);
                io_->read(rawExif.pData_, rawExif.size_);
                if (io_->error() || io_->eof()) throw Error(14);
                ByteOrder bo = ExifParser::decode(exifData_, rawExif.pData_, rawExif.size_);
                setByteOrder(bo);
                if (rawExif.size_ > 0 && byteOrder() == invalidByteOrder) {
#ifndef SUPPRESS_WARNINGS
                    std::cerr << "Warning: Failed to decode Exif metadata.\n";
#endif
                    exifData_.clear();
                }
                --search;
                foundExifData = true;
            }
            else if (marker == app1_ && memcmp(buf.pData_ + 2, xmpId_, 29) == 0) {
                if (size < 31) {
                    rc = 6;
                    break;
                }
                // Seek to beginning and read the XMP packet
                io_->seek(31 - bufRead, BasicIo::cur);
                DataBuf xmpPacket(size - 31);
                io_->read(xmpPacket.pData_, xmpPacket.size_);
                if (io_->error() || io_->eof()) throw Error(14);
                xmpPacket_.assign(reinterpret_cast<char*>(xmpPacket.pData_), xmpPacket.size_);
                if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_)) {
#ifndef SUPPRESS_WARNINGS
                    std::cerr << "Warning: Failed to decode XMP metadata.\n";
#endif
                }
                --search;
            }
            else if (   marker == app13_
                     && memcmp(buf.pData_ + 2, Photoshop::ps3Id_, 14) == 0) {
                if (size < 16) {
                    rc = 2;
                    break;
                }
                // Read the rest of the APP13 segment
                io_->seek(16 - bufRead, BasicIo::cur);
                DataBuf psData(size - 16);
                io_->read(psData.pData_, psData.size_);
                if (io_->error() || io_->eof()) throw Error(14);
                const byte *record = 0;
                uint32_t sizeIptc = 0;
                uint32_t sizeHdr = 0;
#ifdef DEBUG
                std::cerr << "Found app13 segment, size = " << size << "\n";
                //hexdump(std::cerr, psData.pData_, psData.size_);
#endif
                // Find actual IPTC data within the APP13 segment
                const byte* pEnd = psData.pData_ + psData.size_;
                const byte* pCur = psData.pData_;
                while (   pCur < pEnd
                       && 0 == Photoshop::locateIptcIrb(pCur,
                                                        static_cast<long>(pEnd - pCur),
                                                        &record,
                                                        &sizeHdr,
                                                        &sizeIptc)) {
                    if (sizeIptc) {
#ifdef DEBUG
                        std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n";
#endif
                        append(iptcBlob, record + sizeHdr, sizeIptc);
                    }
                    pCur = record + sizeHdr + sizeIptc;
                    pCur += (sizeIptc & 1);
                }
                foundPsData = true;
            }
            else if (marker == com_ && comment_.empty())
            {
                if (size < 2) {
                    rc = 3;
                    break;
                }
                // JPEGs can have multiple comments, but for now only read
                // the first one (most jpegs only have one anyway). Comments
                // are simple single byte ISO-8859-1 strings.
                io_->seek(2 - bufRead, BasicIo::cur);
                DataBuf comment(size - 2);
                io_->read(comment.pData_, comment.size_);
                if (io_->error() || io_->eof()) throw Error(14);
                comment_.assign(reinterpret_cast<char*>(comment.pData_), comment.size_);
                while (   comment_.length()
                       && comment_.at(comment_.length()-1) == '\0') {
                    comment_.erase(comment_.length()-1);
                }
                --search;
            }
            else if (   pixelHeight_ == 0
                     && (   marker == sof0_  || marker == sof1_  || marker == sof2_
                         || marker == sof3_  || marker == sof5_  || marker == sof6_
                         || marker == sof7_  || marker == sof9_  || marker == sof10_
                         || marker == sof11_ || marker == sof13_ || marker == sof14_
                         || marker == sof15_)) {
                // We hit a SOFn (start-of-frame) marker
                if (size < 8) {
                    rc = 7;
                    break;
                }
                pixelHeight_ = getUShort(buf.pData_ + 3, bigEndian);
                pixelWidth_ = getUShort(buf.pData_ + 5, bigEndian);
                if (pixelHeight_ != 0) --search;
                // Skip the remainder of the segment
                io_->seek(size-bufRead, BasicIo::cur);
            }
            else {
                if (size < 2) {
                    rc = 4;
                    break;
                }
                // Skip the remainder of the unknown segment
                if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14);
            }
            // Read the beginning of the next segment
            marker = advanceToMarker();
            if (marker < 0) {
                rc = 5;
                break;
            }
        } // while there are segments to process

        if (   iptcBlob.size() > 0
            && IptcParser::decode(iptcData_,
                                  &iptcBlob[0],
                                  static_cast<uint32_t>(iptcBlob.size()))) {
#ifndef SUPPRESS_WARNINGS
            std::cerr << "Warning: Failed to decode IPTC metadata.\n";
#endif
            iptcData_.clear();
        }

        if (rc != 0) {
#ifndef SUPPRESS_WARNINGS
            std::cerr << "Warning: JPEG format error, rc = " << rc << "\n";
#endif
        }
    } // JpegBase::readMetadata
Ejemplo n.º 29
0
isc_result_t
ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
	int b;
	isc_result_t status;
	int tmp; /* XXX used to force a signed comparison below */

	/* Make section right. */
	if ((tmp = section) < 0 || section >= ns_s_max)
		return ISC_R_NOTIMPLEMENTED;
	if (section != handle->_sect)
		setsection(handle, section);

	/* Make rrnum right. */
	if (rrnum == -1)
		rrnum = handle->_rrnum;
	if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
		return ISC_R_UNKNOWNATTRIBUTE;
	if (rrnum < handle->_rrnum)
		setsection(handle, section);
	if (rrnum > handle->_rrnum) {
		status = ns_skiprr(handle->_ptr, handle->_eom, section,
			      rrnum - handle->_rrnum, &b);

		if (status != ISC_R_SUCCESS)
			return status;
		handle->_ptr += b;
		handle->_rrnum = rrnum;
	}

	/* Do the parse. */
	b = dn_expand(handle->_msg, handle->_eom,
		      handle->_ptr, rr->name, NS_MAXDNAME);
	if (b < 0)
		return ISC_R_FORMERR;
	handle->_ptr += b;
	if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
		return ISC_R_INCOMPLETE;
	rr->type = getUShort (handle->_ptr);
	handle -> _ptr += 2;
	rr->rr_class = getUShort (handle->_ptr);
	handle -> _ptr += 2;
	if (section == ns_s_qd) {
		rr->ttl = 0;
		rr->rdlength = 0;
		rr->rdata = NULL;
	} else {
		if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
			return ISC_R_INCOMPLETE;
		rr->ttl = getULong (handle->_ptr);
		handle -> _ptr += 4;
		rr->rdlength = getUShort (handle->_ptr);
		handle -> _ptr += 2;
		if (handle->_ptr + rr->rdlength > handle->_eom)
			return ISC_R_INCOMPLETE;
		rr->rdata = handle->_ptr;
		handle->_ptr += rr->rdlength;
	}
	if (++handle->_rrnum > handle->_counts[(int)section])
		setsection(handle, (ns_sect)((int)section + 1));

	/* All done. */
	return ISC_R_SUCCESS;
}
Ejemplo n.º 30
0
/*
 * Format the specified option so that a human can easily read it.
 */
char *
pretty_print_option(unsigned int code, struct option_data *option,
    int emit_punct)
{
	static char optbuf[32768]; /* XXX */
	int hunksize = 0, numhunk = -1, numelem = 0;
	char fmtbuf[32], *op = optbuf;
	int i, j, k, opleft = sizeof(optbuf);
	unsigned char *data = option->data;
	unsigned char *dp = data;
	int len = option->len;
	int opcount = 0;
	struct in_addr foo;
	char comma;

	memset(optbuf, 0, sizeof(optbuf));

	/* Code should be between 0 and 255. */
	if (code > 255) {
		warning("pretty_print_option: bad code %d", code);
		goto done;
	}

	if (emit_punct)
		comma = ',';
	else
		comma = ' ';

	/* Figure out the size of the data. */
	for (i = 0; dhcp_options[code].format[i]; i++) {
		if (!numhunk) {
			warning("%s: Excess information in format string: %s",
			    dhcp_options[code].name,
			    &(dhcp_options[code].format[i]));
			goto done;
		}
		numelem++;
		fmtbuf[i] = dhcp_options[code].format[i];
		switch (dhcp_options[code].format[i]) {
		case 'A':
			--numelem;
			fmtbuf[i] = 0;
			numhunk = 0;
			if (hunksize == 0) {
				warning("%s: no size indicator before A"
				    " in format string: %s",
				    dhcp_options[code].name,
				    dhcp_options[code].format);
				goto done;
			}
			break;
		case 'X':
			for (k = 0; k < len; k++)
				if (!isascii(data[k]) ||
				    !isprint(data[k]))
					break;
			if (k == len) {
				fmtbuf[i] = 't';
				numhunk = -2;
			} else {
				hunksize++;
				comma = ':';
				numhunk = 0;
			}
			fmtbuf[i + 1] = 0;
			break;
		case 't':
			fmtbuf[i + 1] = 0;
			numhunk = -2;
			break;
		case 'I':
		case 'l':
		case 'L':
			hunksize += 4;
			break;
		case 'S':
			hunksize += 2;
			break;
		case 'B':
		case 'f':
			hunksize++;
			break;
		case 'e':
			break;
		case 'C':
			hunksize += 5;
			break;
		default:
			warning("%s: garbage in format string: %s",
			    dhcp_options[code].name,
			    &(dhcp_options[code].format[i]));
			goto done;
		}
	}

	/* Check for too few bytes. */
	if (hunksize > len) {
		warning("%s: expecting at least %d bytes; got %d",
		    dhcp_options[code].name, hunksize, len);
		goto done;
	}
	/* Check for too many bytes. */
	if (numhunk == -1 && hunksize < len) {
		warning("%s: expecting only %d bytes: got %d",
		    dhcp_options[code].name, hunksize, len);
		goto done;
	}

	/* If this is an array, compute its size. */
	if (!numhunk)
		numhunk = len / hunksize;
	/* See if we got an exact number of hunks. */
	if (numhunk > 0 && numhunk * hunksize != len) {
		warning("%s: expecting %d bytes: got %d",
		    dhcp_options[code].name, numhunk * hunksize, len);
		goto done;
	}

	/* A one-hunk array prints the same as a single hunk. */
	if (numhunk < 0)
		numhunk = 1;

	/* Cycle through the array (or hunk) printing the data. */
	for (i = 0; i < numhunk; i++) {
		for (j = 0; j < numelem; j++) {
			switch (fmtbuf[j]) {
			case 't':
				opcount = pretty_print_string(op, opleft,
				    dp, len, emit_punct);
				break;
			case 'I':
				foo.s_addr = htonl(getULong(dp));
				opcount = snprintf(op, opleft, "%s",
				    inet_ntoa(foo));
				dp += 4;
				break;
			case 'l':
				opcount = snprintf(op, opleft, "%ld",
				    (long)getLong(dp));
				dp += 4;
				break;
			case 'L':
				opcount = snprintf(op, opleft, "%lu",
				    (unsigned long)getULong(dp));
				dp += 4;
				break;
			case 'S':
				opcount = snprintf(op, opleft, "%u",
				    getUShort(dp));
				dp += 2;
				break;
			case 'B':
				opcount = snprintf(op, opleft, "%u", *dp);
				dp++;
				break;
			case 'X':
				opcount = snprintf(op, opleft, "%x", *dp);
				dp++;
				break;
			case 'f':
				opcount = snprintf(op, opleft, "%s",
				    *dp ? "true" : "false");
				dp++;
				break;
			case 'C':
				memset(&foo, 0, sizeof(foo));
				memcpy(&foo.s_addr, dp+1, (*dp + 7) / 8); 
				opcount = snprintf(op, opleft, "%s/%u",
				    inet_ntoa(foo), *dp); 
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				dp += 1 + (*dp + 7) / 8;
 				break;
			default:
				warning("Unexpected format code %c", fmtbuf[j]);
				goto toobig;
			}
			if (opcount >= opleft || opcount == -1)
				goto toobig;
			opleft -= opcount;
			op += opcount;
			if (j + 1 < numelem && comma != ':') {
				opcount = snprintf(op, opleft, " ");
				if (opcount >= opleft || opcount == -1)
					goto toobig;
				opleft -= opcount;
				op += opcount;
			}
		}
		if (i + 1 < numhunk) {
			opcount = snprintf(op, opleft, "%c", comma);
			if (opcount >= opleft || opcount == -1)
				goto toobig;
			opleft -= opcount;
			op += opcount;
		}
	}

done:
	return (optbuf);

toobig:
	memset(optbuf, 0, sizeof(optbuf));
	return (optbuf);
}