예제 #1
0
  protected int getDataSize() {
    if (!isExternalReferences()) {
      return SMALL_RECORD_SIZE;
    }
    int sum = 2; // u16 number of sheets

    sum += StringUtil.getEncodedSize(field_2_encoded_url);

    for (int i = 0; i < field_3_sheet_names.length; i++) {
      sum += StringUtil.getEncodedSize(field_3_sheet_names[i]);
    }
    return sum;
  }
예제 #2
0
  public void serialize(LittleEndianOutput out) {
    out.writeShort(field_1_number_of_sheets);

    if (isExternalReferences()) {
      StringUtil.writeUnicodeString(out, field_2_encoded_url);

      for (int i = 0; i < field_3_sheet_names.length; i++) {
        StringUtil.writeUnicodeString(out, field_3_sheet_names[i]);
      }
    } else {
      int field2val = _isAddInFunctions ? TAG_ADD_IN_FUNCTIONS : TAG_INTERNAL_REFERENCES;

      out.writeShort(field2val);
    }
  }
 @Override
 protected int getDataSize() {
   if (_name == null) {
     return BASE_SIZE;
   }
   return BASE_SIZE
       + 1 // unicode flag
       + _name.length() * (StringUtil.hasMultibyte(_name) ? 2 : 1);
 }
예제 #4
0
  public void serialize(LittleEndianOutput out) {
    _range.serialize(out);

    _guid.serialize(out);
    out.writeInt(0x00000002); // TODO const
    out.writeInt(_linkOpts);

    if ((_linkOpts & HLINK_LABEL) != 0) {
      out.writeInt(_label.length());
      StringUtil.putUnicodeLE(_label, out);
    }
    if ((_linkOpts & HLINK_TARGET_FRAME) != 0) {
      out.writeInt(_targetFrame.length());
      StringUtil.putUnicodeLE(_targetFrame, out);
    }

    if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) != 0) {
      out.writeInt(_address.length());
      StringUtil.putUnicodeLE(_address, out);
    }

    if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) == 0) {
      _moniker.serialize(out);
      if (URL_MONIKER.equals(_moniker)) {
        if (_uninterpretedTail == null) {
          out.writeInt(_address.length() * 2);
          StringUtil.putUnicodeLE(_address, out);
        } else {
          out.writeInt(_address.length() * 2 + TAIL_SIZE);
          StringUtil.putUnicodeLE(_address, out);
          writeTail(_uninterpretedTail, out);
        }
      } else if (FILE_MONIKER.equals(_moniker)) {
        out.writeShort(_fileOpts);
        out.writeInt(_shortFilename.length());
        StringUtil.putCompressedUnicode(_shortFilename, out);
        writeTail(_uninterpretedTail, out);
        if (_address == null) {
          out.writeInt(0);
        } else {
          int addrLen = _address.length() * 2;
          out.writeInt(addrLen + 6);
          out.writeInt(addrLen);
          out.writeShort(0x0003); // TODO const
          StringUtil.putUnicodeLE(_address, out);
        }
      }
    }
    if ((_linkOpts & HLINK_PLACE) != 0) {
      out.writeInt(_textMark.length());
      StringUtil.putUnicodeLE(_textMark, out);
    }
  }
예제 #5
0
  static void write(Sttb sttb, HWPFOutputStream tableStream) throws IOException {
    final int headerSize = sttb.cDataLength == 2 ? 6 : 8;

    byte[] header = new byte[headerSize];
    LittleEndian.putShort(header, 0, (short) 0xffff);

    if (sttb.data == null || sttb.data.length == 0) {
      if (sttb.cDataLength == 4) {
        LittleEndian.putInt(header, 2, 0);
        LittleEndian.putUShort(header, 6, sttb.cbExtra);
        tableStream.write(header);
        return;
      }

      LittleEndian.putUShort(header, 2, 0);
      LittleEndian.putUShort(header, 4, sttb.cbExtra);
      tableStream.write(header);
      return;
    }

    if (sttb.cDataLength == 4) {
      LittleEndian.putInt(header, 2, sttb.data.length);
      LittleEndian.putUShort(header, 6, sttb.cbExtra);
      tableStream.write(header);
    } else {
      LittleEndian.putUShort(header, 2, sttb.data.length);
      LittleEndian.putUShort(header, 4, sttb.cbExtra);
      tableStream.write(header);
    }

    for (int i = 0; i < sttb.data.length; i++) {
      String entry = sttb.data[i];
      if (entry == null) {
        // is it correct?
        tableStream.write(new byte[] {-1, 0});
        continue;
      }

      byte[] buf = new byte[entry.length() * 2 + sttb.cbExtra + 2];

      LittleEndian.putShort(buf, 0, (short) entry.length());
      StringUtil.putUnicodeLE(entry, buf, 2);

      if (sttb.extraData != null && i < sttb.extraData.length && sttb.extraData[i] != null)
        System.arraycopy(
            sttb.extraData[i],
            0,
            buf,
            entry.length() * 2,
            Math.min(sttb.extraData[i].length, sttb.cbExtra));

      tableStream.write(buf);
    }
  }
  @Override
  protected void serialize(LittleEndianOutput out) {

    out.writeShort(_sxaxis);
    out.writeShort(_cSub);
    out.writeShort(_grbitSub);
    out.writeShort(_cItm);

    if (_name != null) {
      StringUtil.writeUnicodeString(out, _name);
    } else {
      out.writeShort(STRING_NOT_PRESENT_LEN);
    }
  }
예제 #7
0
  static Sttb read(int cDataLength, byte[] buffer, int startOffset) {
    short ffff = LittleEndian.getShort(buffer, startOffset);
    int offset = startOffset + 2;

    if (ffff != (short) 0xffff) {
      // Non-extended character Pascal strings
      throw new UnsupportedOperationException(
          "Non-extended character Pascal strings are not supported right now. "
              + "Please, contact POI developers for update.");
    }
    // strings are extended character strings

    int cData =
        cDataLength == 2
            ? LittleEndian.getUShort(buffer, offset)
            : LittleEndian.getInt(buffer, offset);
    offset += cDataLength;

    Sttb sttb = new Sttb();
    sttb.cDataLength = cDataLength;
    sttb.cbExtra = LittleEndian.getUShort(buffer, offset);
    offset += 2;

    sttb.data = new String[cData];
    sttb.extraData = new byte[cData][];

    for (int i = 0; i < cData; i++) {
      int cchData = LittleEndian.getShort(buffer, offset);
      offset += 2;

      if (cchData < 0) continue;

      sttb.data[i] = StringUtil.getFromUnicodeLE(buffer, offset, cchData);
      offset += cchData * 2;

      sttb.extraData[i] = LittleEndian.getByteArray(buffer, offset, sttb.cbExtra);
      offset += sttb.cbExtra;
    }

    return sttb;
  }
  public MAPIStringAttribute(MAPIProperty property, int type, byte[] data) {
    super(property, type, data);

    String tmpData = null;
    if (type == Types.ASCII_STRING) {
      try {
        tmpData = new String(data, CODEPAGE);
      } catch (UnsupportedEncodingException e) {
        throw new RuntimeException("JVM Broken - core encoding " + CODEPAGE + " missing");
      }
    } else if (type == Types.UNICODE_STRING) {
      tmpData = StringUtil.getFromUnicodeLE(data);
    } else {
      throw new IllegalArgumentException("Not a string type " + type);
    }

    // Strip off the null terminator if present
    if (tmpData.endsWith("\0")) {
      tmpData = tmpData.substring(0, tmpData.length() - 1);
    }
    this.data = tmpData;
  }
예제 #9
0
    protected void serialize(ContinuableRecordOutput out) {
      int dataSize = getDataSize();

      out.writeContinueIfRequired(8);
      out.writeShort(reserved);
      out.writeShort(dataSize);
      out.writeShort(formattingFontIndex);
      out.writeShort(formattingOptions);

      out.writeContinueIfRequired(6);
      out.writeShort(numberOfRuns);
      out.writeShort(phoneticText.length());
      out.writeShort(phoneticText.length());

      out.writeContinueIfRequired(phoneticText.length() * 2);
      StringUtil.putUnicodeLE(phoneticText, out);

      for (int i = 0; i < phRuns.length; i++) {
        phRuns[i].serialize(out);
      }

      out.write(extraData);
    }
  public EmbeddedObjectRefSubRecord(LittleEndianInput in, int size) {

    // Much guess-work going on here due to lack of any documentation.
    // See similar source code in OOO:
    // http://svn.services.openoffice.org/ooo/trunk/sc/source/filter/excel/xiescher.cxx
    // 1223 void XclImpOleObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nRecSize )

    int streamIdOffset = in.readShort(); // OOO calls this 'nFmlaLen'
    int remaining = size - LittleEndian.SHORT_SIZE;

    int dataLenAfterFormula = remaining - streamIdOffset;
    int formulaSize = in.readUShort();
    remaining -= LittleEndian.SHORT_SIZE;
    field_1_unknown_int = in.readInt();
    remaining -= LittleEndian.INT_SIZE;
    byte[] formulaRawBytes = readRawData(in, formulaSize);
    remaining -= formulaSize;
    field_2_refPtg = readRefPtg(formulaRawBytes);
    if (field_2_refPtg == null) {
      // common case
      // field_2_n16 seems to be 5 here
      // The formula almost looks like tTbl but the row/column values seem like garbage.
      field_2_unknownFormulaData = formulaRawBytes;
    } else {
      field_2_unknownFormulaData = null;
    }

    int stringByteCount;
    if (remaining >= dataLenAfterFormula + 3) {
      int tag = in.readByte();
      stringByteCount = LittleEndian.BYTE_SIZE;
      if (tag != 0x03) {
        throw new RecordFormatException("Expected byte 0x03 here");
      }
      int nChars = in.readUShort();
      stringByteCount += LittleEndian.SHORT_SIZE;
      if (nChars > 0) {
        // OOO: the 4th way Xcl stores a unicode string: not even a Grbit byte present if length 0
        field_3_unicode_flag = (in.readByte() & 0x01) != 0;
        stringByteCount += LittleEndian.BYTE_SIZE;
        if (field_3_unicode_flag) {
          field_4_ole_classname = StringUtil.readUnicodeLE(in, nChars);
          stringByteCount += nChars * 2;
        } else {
          field_4_ole_classname = StringUtil.readCompressedUnicode(in, nChars);
          stringByteCount += nChars;
        }
      } else {
        field_4_ole_classname = "";
      }
    } else {
      field_4_ole_classname = null;
      stringByteCount = 0;
    }
    remaining -= stringByteCount;
    // Pad to next 2-byte boundary
    if (((stringByteCount + formulaSize) % 2) != 0) {
      int b = in.readByte();
      remaining -= LittleEndian.BYTE_SIZE;
      if (field_2_refPtg != null && field_4_ole_classname == null) {
        field_4_unknownByte = Byte.valueOf((byte) b);
      }
    }
    int nUnexpectedPadding = remaining - dataLenAfterFormula;

    if (nUnexpectedPadding > 0) {
      logger.log(
          POILogger.ERROR, "Discarding " + nUnexpectedPadding + " unexpected padding bytes ");
      readRawData(in, nUnexpectedPadding);
      remaining -= nUnexpectedPadding;
    }

    // Fetch the stream ID
    if (dataLenAfterFormula >= 4) {
      field_5_stream_id = Integer.valueOf(in.readInt());
      remaining -= LittleEndian.INT_SIZE;
    } else {
      field_5_stream_id = null;
    }
    field_6_unknown = readRawData(in, remaining);
  }
  public void serialize(LittleEndianOutput out) {

    int formulaSize =
        field_2_refPtg == null ? field_2_unknownFormulaData.length : field_2_refPtg.getSize();
    int idOffset = getStreamIDOffset(formulaSize);
    int dataSize = getDataSize(idOffset);

    out.writeShort(sid);
    out.writeShort(dataSize);

    out.writeShort(idOffset);
    out.writeShort(formulaSize);
    out.writeInt(field_1_unknown_int);

    int pos = 12;

    if (field_2_refPtg == null) {
      out.write(field_2_unknownFormulaData);
    } else {
      field_2_refPtg.write(out);
    }
    pos += formulaSize;

    int stringLen;
    if (field_4_ole_classname == null) {
      // don't write 0x03, stringLen, flag, text
      stringLen = 0;
    } else {
      out.writeByte(0x03);
      pos += 1;
      stringLen = field_4_ole_classname.length();
      out.writeShort(stringLen);
      pos += 2;
      if (stringLen > 0) {
        out.writeByte(field_3_unicode_flag ? 0x01 : 0x00);
        pos += 1;

        if (field_3_unicode_flag) {
          StringUtil.putUnicodeLE(field_4_ole_classname, out);
          pos += stringLen * 2;
        } else {
          StringUtil.putCompressedUnicode(field_4_ole_classname, out);
          pos += stringLen;
        }
      }
    }

    // pad to next 2-byte boundary (requires 0 or 1 bytes)
    switch (idOffset - (pos - 6)) { // 6 for 3 shorts: sid, dataSize, idOffset
      case 1:
        out.writeByte(field_4_unknownByte == null ? 0x00 : field_4_unknownByte.intValue());
        pos++;
      case 0:
        break;
      default:
        throw new IllegalStateException("Bad padding calculation (" + idOffset + ", " + pos + ")");
    }

    if (field_5_stream_id != null) {
      out.writeInt(field_5_stream_id.intValue());
      pos += 4;
    }
    out.write(field_6_unknown);
  }
예제 #12
0
  public HyperlinkRecord(RecordInputStream in) {
    _range = new CellRangeAddress(in);

    _guid = new GUID(in);

    /**
     * streamVersion (4 bytes): An unsigned integer that specifies the version number of the
     * serialization implementation used to save this structure. This value MUST equal 2.
     */
    int streamVersion = in.readInt();
    if (streamVersion != 0x00000002) {
      throw new RecordFormatException("Stream Version must be 0x2 but found " + streamVersion);
    }
    _linkOpts = in.readInt();

    if ((_linkOpts & HLINK_LABEL) != 0) {
      int label_len = in.readInt();
      _label = in.readUnicodeLEString(label_len);
    }

    if ((_linkOpts & HLINK_TARGET_FRAME) != 0) {
      int len = in.readInt();
      _targetFrame = in.readUnicodeLEString(len);
    }

    if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) != 0) {
      _moniker = null;
      int nChars = in.readInt();
      _address = in.readUnicodeLEString(nChars);
    }

    if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) == 0) {
      _moniker = new GUID(in);

      if (URL_MONIKER.equals(_moniker)) {
        int length = in.readInt();
        /**
         * The value of <code>length<code> be either the byte size of the url field
         * (including the terminating NULL character) or the byte size of the url field plus 24.
         * If the value of this field is set to the byte size of the url field,
         * then the tail bytes fields are not present.
         */
        int remaining = in.remaining();
        if (length == remaining) {
          int nChars = length / 2;
          _address = in.readUnicodeLEString(nChars);
        } else {
          int nChars = (length - TAIL_SIZE) / 2;
          _address = in.readUnicodeLEString(nChars);
          /**
           * TODO: make sense of the remaining bytes According to the spec they consist of: 1.
           * 16-byte GUID: This field MUST equal {0xF4815879, 0x1D3B, 0x487F, 0xAF, 0x2C, 0x82,
           * 0x5D, 0xC4, 0x85, 0x27, 0x63} 2. Serial version, this field MUST equal 0 if present. 3.
           * URI Flags
           */
          _uninterpretedTail = readTail(URL_TAIL, in);
        }
      } else if (FILE_MONIKER.equals(_moniker)) {
        _fileOpts = in.readShort();

        int len = in.readInt();
        _shortFilename = StringUtil.readCompressedUnicode(in, len);
        _uninterpretedTail = readTail(FILE_TAIL, in);
        int size = in.readInt();
        if (size > 0) {
          int charDataSize = in.readInt();

          // From the spec: An optional unsigned integer that MUST be 3 if present
          // but some files has 4
          int usKeyValue = in.readUShort();

          _address = StringUtil.readUnicodeLE(in, charDataSize / 2);
        } else {
          _address = null;
        }
      } else if (STD_MONIKER.equals(_moniker)) {
        _fileOpts = in.readShort();

        int len = in.readInt();

        byte[] path_bytes = new byte[len];
        in.readFully(path_bytes);

        _address = new String(path_bytes);
      }
    }

    if ((_linkOpts & HLINK_PLACE) != 0) {

      int len = in.readInt();
      _textMark = in.readUnicodeLEString(len);
    }

    if (in.remaining() > 0) {
      logger.log(
          POILogger.WARN,
          "Hyperlink data remains: " + in.remaining() + " : " + HexDump.toHex(in.readRemainder()));
    }
  }
예제 #13
0
 /** Sets the string represented by this record. */
 public void setString(String string) {
   _text = string;
   _is16bitUnicode = StringUtil.hasMultibyte(string);
 }
예제 #14
0
    protected ExtRst(LittleEndianInput in, int expectedLength) {
      reserved = in.readShort();

      // Old style detection (Reserved = 0xFF)
      if (reserved == -1) {
        populateEmpty();
        return;
      }

      // Spot corrupt records
      if (reserved != 1) {
        System.err.println(
            "Warning - ExtRst was has wrong magic marker, expecting 1 but found "
                + reserved
                + " - ignoring");
        // Grab all the remaining data, and ignore it
        for (int i = 0; i < expectedLength - 2; i++) {
          in.readByte();
        }
        // And make us be empty
        populateEmpty();
        return;
      }

      // Carry on reading in as normal
      short stringDataSize = in.readShort();

      formattingFontIndex = in.readShort();
      formattingOptions = in.readShort();

      // RPHSSub
      numberOfRuns = in.readUShort();
      short length1 = in.readShort();
      // No really. Someone clearly forgot to read
      //  the docs on their datastructure...
      short length2 = in.readShort();
      // And sometimes they write out garbage :(
      if (length1 == 0 && length2 > 0) {
        length2 = 0;
      }
      if (length1 != length2) {
        throw new IllegalStateException(
            "The two length fields of the Phonetic Text don't agree! "
                + length1
                + " vs "
                + length2);
      }
      phoneticText = StringUtil.readUnicodeLE(in, length1);

      int runData = stringDataSize - 4 - 6 - (2 * phoneticText.length());
      int numRuns = (runData / 6);
      phRuns = new PhRun[numRuns];
      for (int i = 0; i < phRuns.length; i++) {
        phRuns[i] = new PhRun(in);
      }

      int extraDataLength = runData - (numRuns * 6);
      if (extraDataLength < 0) {
        System.err.println("Warning - ExtRst overran by " + (0 - extraDataLength) + " bytes");
        extraDataLength = 0;
      }
      extraData = new byte[extraDataLength];
      for (int i = 0; i < extraData.length; i++) {
        extraData[i] = in.readByte();
      }
    }