예제 #1
0
        /// <summary>
        /// Writes a variant value To an output stream. This method ensures that
        /// always a multiple of 4 bytes is written.
        /// If the codepage is UTF-16, which is encouraged, strings
        /// <strong>must</strong> always be written as {@link Variant#VT_LPWSTR}
        /// strings, not as {@link Variant#VT_LPSTR} strings. This method ensure this
        /// by Converting strings appropriately, if needed.
        /// </summary>
        /// <param name="out1">The stream To Write the value To.</param>
        /// <param name="type">The variant's type.</param>
        /// <param name="value">The variant's value.</param>
        /// <param name="codepage">The codepage To use To Write non-wide strings</param>
        /// <returns>The number of entities that have been written. In many cases an
        /// "entity" is a byte but this is not always the case.</returns>
        public static int Write(Stream out1, long type,
                                Object value, int codepage)
        {
            int length = 0;

            switch ((int)type)
            {
            case Variant.VT_BOOL:
            {
                byte[] data = new byte[2];
                if ((bool)value)
                {
                    out1.WriteByte(0xFF);
                    out1.WriteByte(0xFF);
                }
                else
                {
                    out1.WriteByte(0x00);
                    out1.WriteByte(0x00);
                }
                length += 2;
                break;
            }

            case Variant.VT_LPSTR:
            {
                CodePageString codePageString = new CodePageString((String)value,
                                                                   codepage);
                length += codePageString.Write(out1);
                break;
            }

            case Variant.VT_LPWSTR:
            {
                int nrOfChars = ((String)value).Length + 1;
                length += TypeWriter.WriteUIntToStream(out1, (uint)nrOfChars);
                char[] s = ((String)value).ToCharArray();
                for (int i = 0; i < s.Length; i++)
                {
                    int  high  = ((s[i] & 0x0000ff00) >> 8);
                    int  low   = (s[i] & 0x000000ff);
                    byte highb = (byte)high;
                    byte lowb  = (byte)low;
                    out1.WriteByte(lowb);
                    out1.WriteByte(highb);
                    length += 2;
                }
                // NullTerminator
                out1.WriteByte(0x00);
                out1.WriteByte(0x00);
                length += 2;
                break;
            }

            case Variant.VT_CF:
            {
                byte[] b = (byte[])value;
                out1.Write(b, 0, b.Length);
                length = b.Length;
                break;
            }

            case Variant.VT_EMPTY:
            {
                length += TypeWriter.WriteUIntToStream(out1, Variant.VT_EMPTY);
                break;
            }

            case Variant.VT_I2:
            {
                short x;
                try
                {
                    x = Convert.ToInt16(value, CultureInfo.InvariantCulture);
                }
                catch (OverflowException)
                {
                    x = (short)((int)value);
                }
                length += TypeWriter.WriteToStream(out1, x);
                //length = LittleEndianConsts.SHORT_SIZE;
                break;
            }

            case Variant.VT_I4:
            {
                if (!(value is int))
                {
                    throw new Exception("Could not cast an object To "
                                        + "int" + ": "
                                        + value.GetType().Name + ", "
                                        + value.ToString());
                }
                length += TypeWriter.WriteToStream(out1, (int)value);
                break;
            }

            case Variant.VT_I8:
            {
                length += TypeWriter.WriteToStream(out1, Convert.ToInt64(value, CultureInfo.CurrentCulture));
                break;
            }

            case Variant.VT_R8:
            {
                length += TypeWriter.WriteToStream(out1,
                                                   (Double)value);
                break;
            }

            case Variant.VT_FILETIME:
            {
                long filetime;
                if (value != null)
                {
                    filetime = Util.DateToFileTime((DateTime)value);
                }
                else
                {
                    filetime = 0;
                }
                int      high          = (int)((filetime >> 32) & 0x00000000FFFFFFFFL);
                int      low           = (int)(filetime & 0x00000000FFFFFFFFL);
                Filetime filetimeValue = new Filetime(low, high);
                length += filetimeValue.Write(out1);
                //length += TypeWriter.WriteUIntToStream
                //    (out1, (uint)(0x0000000FFFFFFFFL & low));
                //length += TypeWriter.WriteUIntToStream
                //    (out1, (uint)(0x0000000FFFFFFFFL & high));

                break;
            }

            default:
            {
                /* The variant type is not supported yet. However, if the value
                 * is a byte array we can Write it nevertheless. */
                if (value is byte[])
                {
                    byte[] b = (byte[])value;
                    out1.Write(b, 0, b.Length);
                    length = b.Length;
                    WriteUnsupportedTypeMessage
                        (new WritingNotSupportedException(type, value));
                }
                else
                {
                    throw new WritingNotSupportedException(type, value);
                }
                break;
            }
            }
            /* pad values to 4-bytes */
            while ((length & 0x3) != 0)
            {
                out1.WriteByte(0x00);
                length++;
            }
            return(length);
        }
예제 #2
0
        /// <summary>
        /// Reads a variant type from a byte array
        /// </summary>
        /// <param name="src">The byte array</param>
        /// <param name="offset">The offset in the byte array where the variant starts</param>
        /// <param name="length">The Length of the variant including the variant type field</param>
        /// <param name="type">The variant type To Read</param>
        /// <param name="codepage">The codepage To use for non-wide strings</param>
        /// <returns>A Java object that corresponds best To the variant field. For
        /// example, a VT_I4 is returned as a {@link long}, a VT_LPSTR as a
        /// {@link String}.</returns>
        public static Object Read(byte[] src, int offset,
                                  int length, long type, int codepage)
        {
            TypedPropertyValue typedPropertyValue = new TypedPropertyValue(
                (int)type, null);
            int unpadded;

            try
            {
                unpadded = typedPropertyValue.ReadValue(src, offset);
            }
            catch (InvalidOperationException)
            {
                int    propLength = Math.Min(length, src.Length - offset);
                byte[] v          = new byte[propLength];
                System.Array.Copy(src, offset, v, 0, propLength);
                throw new ReadingNotSupportedException(type, v);
            }

            switch ((int)type)
            {
            case Variant.VT_EMPTY:
            case Variant.VT_I4:
            case Variant.VT_I8:
            case Variant.VT_R8:
                /*
                 * we have more property types that can be converted into Java
                 * objects, but current API need to be preserved, and it returns
                 * other types as byte arrays. In future major versions it shall be
                 * changed -- sergey
                 */
                return(typedPropertyValue.Value);

            case Variant.VT_I2:
            {
                /*
                 * also for backward-compatibility with prev. versions of POI
                 * --sergey
                 */
                return((short)typedPropertyValue.Value);
            }

            case Variant.VT_FILETIME:
            {
                Filetime filetime = (Filetime)typedPropertyValue.Value;
                return(Util.FiletimeToDate((int)filetime.High,
                                           (int)filetime.Low));
            }

            case Variant.VT_LPSTR:
            {
                CodePageString string1 = (CodePageString)typedPropertyValue.Value;
                return(string1.GetJavaValue(codepage));
            }

            case Variant.VT_LPWSTR:
            {
                UnicodeString string1 = (UnicodeString)typedPropertyValue.Value;
                return(string1.ToJavaString());
            }

            case Variant.VT_CF:
            {
                // if(l1 < 0) {

                /*
                 * YK: reading the ClipboardData packet (VT_CF) is not quite
                 * correct. The size of the data is determined by the first four
                 * bytes of the packet while the current implementation calculates
                 * it in the Section constructor. Test files in Bugzilla 42726 and
                 * 45583 clearly show that this approach does not always work. The
                 * workaround below attempts to gracefully handle such cases instead
                 * of throwing exceptions.
                 *
                 * August 20, 2009
                 */
                // l1 = LittleEndian.getInt(src, o1); o1 += LittleEndian.INT_SIZE;
                // }
                // final byte[] v = new byte[l1];
                // System.arraycopy(src, o1, v, 0, v.length);
                // value = v;
                // break;
                ClipboardData clipboardData = (ClipboardData)typedPropertyValue.Value;
                return(clipboardData.ToByteArray());
            }

            case Variant.VT_BOOL:
            {
                VariantBool bool1 = (VariantBool)typedPropertyValue.Value;
                return((bool)bool1.Value);
            }

            default:
            {
                /*
                 * it is not very good, but what can do without breaking current
                 * API? --sergey
                 */
                byte[] v = new byte[unpadded];
                System.Array.Copy(src, offset, v, 0, unpadded);
                throw new ReadingNotSupportedException(type, v);
            }
            }
        }