CurlSharp.NativeMethods.curl_formadd C# (CSharp) Method

curl_formadd() private method

private curl_formadd ( IntPtr &pHttppost, IntPtr &pLastPost, int codeFirst, IntPtr bufFirst, int codeNext, IntPtr bufNext, int codeLast ) : int
pHttppost System.IntPtr
pLastPost System.IntPtr
codeFirst int
bufFirst System.IntPtr
codeNext int
bufNext System.IntPtr
codeLast int
return int
		internal static extern int curl_formadd (ref IntPtr pHttppost, ref IntPtr pLastPost,
		                                         int codeFirst, IntPtr bufFirst,
		                                         int codeNext, IntPtr bufNext,
		                                         int codeLast);
		#endif

Usage Example

Ejemplo n.º 1
0
        /// <summary>
        ///     Add a multi-part form section.
        /// </summary>
        /// <param name="args">
        ///     Argument list, as described in the remarks.
        /// </param>
        /// <returns>
        ///     A <see cref="CurlFormCode" />, hopefully
        ///     <c>CurlFormCode.Ok</c>.
        /// </returns>
        /// <remarks>
        ///     This is definitely the workhorse method for this class. It
        ///     should be called in roughly the same manner as
        ///     <c>curl_formadd()</c>, except you would omit the first two
        ///     <c>struct curl_httppost**</c> arguments (<c>firstitem</c> and
        ///     <c>lastitem</c>), which are wrapped in this class. So you should
        ///     pass arguments in the following sequence:
        ///     <para>
        ///         <c>
        ///             CurlHttpMultiPartForm.AddSection(option1, value1, ..., optionX, valueX,
        ///             CurlFormOption.End)
        ///         </c>
        ///         ;
        ///     </para>
        ///     <para>
        ///         For a complete list of possible options, see the documentation for
        ///         the <see cref="CurlFormOption" /> enumeration.
        ///     </para>
        ///     <note>
        ///         The pointer options (<c>PtrName</c>, etc.) make an
        ///         internal copy of the passed <c>byte</c> array. Therefore, any
        ///         changes you make to the client copy of this array AFTER calling
        ///         this method, won't be reflected internally with <c>cURL</c>. The
        ///         purpose of providing the pointer options is to support the
        ///         posting of non-string binary data.
        ///     </note>
        /// </remarks>
        public CurlFormCode AddSection(params object[] args)
        {
            var nCount     = args.Length;
            var nRealCount = nCount;
            var retCode    = CurlFormCode.Ok;

            CurlForms[] aForms = null;

            // one arg or even number of args is an error
            if ((nCount == 1) || (nCount % 2 == 0))
            {
                return(CurlFormCode.Incomplete);
            }

            // ensure the last argument is End
            var iCode = (CurlFormOption)
                        Convert.ToInt32(args.GetValue(nCount - 1));

            if (iCode != CurlFormOption.End)
            {
                return(CurlFormCode.Incomplete);
            }

            // walk through any passed arrays to get the true number of
            // items and ensure the child arrays are properly (and not
            // prematurely) terminated with End
            for (var i = 0; i < nCount; i += 2)
            {
                iCode = (CurlFormOption)Convert.ToInt32(args.GetValue(i));
                switch (iCode)
                {
                case CurlFormOption.Array:
                {
                    aForms = args.GetValue(i + 1) as CurlForms[];
                    if (aForms == null)
                    {
                        return(CurlFormCode.Incomplete);
                    }
                    var nFormsCount = aForms.Length;
                    for (var j = 0; j < nFormsCount; j++)
                    {
                        var pcf = aForms.GetValue(j) as CurlForms;
                        if (pcf == null)
                        {
                            return(CurlFormCode.Incomplete);
                        }
                        if (j == nFormsCount - 1)
                        {
                            if (pcf.Option != CurlFormOption.End)
                            {
                                return(CurlFormCode.Incomplete);
                            }
                        }
                        else
                        {
                            if (pcf.Option == CurlFormOption.End)
                            {
                                return(CurlFormCode.Incomplete);
                            }
                        }
                    }
                    // -2 accounts for the fact that we're a) not
                    // including the item with End and b) not
                    // including Array in what we pass to cURL
                    nRealCount += 2 * (nFormsCount - 2);
                    break;
                }
                }
            }

            // allocate the IntPtr array for the data
            var aPointers = new IntPtr[nRealCount];

            for (var i = 0; i < nRealCount - 1; i++)
            {
                aPointers[i] = IntPtr.Zero;
            }
            aPointers[nRealCount - 1] = (IntPtr)CurlFormOption.End;

            // now we go through the args
            aForms = null;
            var    formArrayPos = 0;
            var    argArrayPos  = 0;
            var    ptrArrayPos  = 0;
            Object obj          = null;

            while ((retCode == CurlFormCode.Ok) &&
                   (ptrArrayPos < nRealCount))
            {
                if (aForms != null)
                {
                    var pcf = aForms.GetValue(formArrayPos++)
                              as CurlForms;
                    if (pcf == null)
                    {
                        retCode = CurlFormCode.UnknownOption;
                        break;
                    }
                    iCode = pcf.Option;
                    obj   = pcf.Value;
                }
                else
                {
                    iCode = (CurlFormOption)Convert.ToInt32(
                        args.GetValue(argArrayPos++));
                    obj = (iCode == CurlFormOption.End)
                        ? null
                        : args.GetValue(argArrayPos++);
                }

                switch (iCode)
                {
                // handle byte-array pointer-related items
                case CurlFormOption.PtrName:
                case CurlFormOption.PtrContents:
                case CurlFormOption.BufferPtr:
                {
                    var bytes = obj as byte[];
                    if (bytes == null)
                    {
                        retCode = CurlFormCode.UnknownOption;
                    }
                    else
                    {
                        var nLen = bytes.Length;
                        var ptr  = Marshal.AllocHGlobal(nLen);
                        if (ptr != IntPtr.Zero)
                        {
                            aPointers[ptrArrayPos++] = (IntPtr)iCode;
                            // copy bytes to unmanaged buffer
                            for (var j = 0; j < nLen; j++)
                            {
                                Marshal.WriteByte(ptr, bytes[j]);
                            }
                            aPointers[ptrArrayPos++] = ptr;
                        }
                        else
                        {
                            retCode = CurlFormCode.Memory;
                        }
                    }
                    break;
                }

                // length values
                case CurlFormOption.NameLength:
                case CurlFormOption.ContentsLength:
                case CurlFormOption.BufferLength:
                    aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    aPointers[ptrArrayPos++] = (IntPtr)
                                               Convert.ToInt32(obj);
                    break;

                // strings
                case CurlFormOption.CopyName:
                case CurlFormOption.CopyContents:
                case CurlFormOption.FileContent:
                case CurlFormOption.File:
                case CurlFormOption.ContentType:
                case CurlFormOption.Filename:
                case CurlFormOption.Buffer:
                {
                    aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    var s = obj as String;
                    if (s == null)
                    {
                        retCode = CurlFormCode.UnknownOption;
                    }
                    else
                    {
                        var p = Marshal.StringToHGlobalAnsi(s);
                        if (p != IntPtr.Zero)
                        {
                            aPointers[ptrArrayPos++] = p;
                        }
                        else
                        {
                            retCode = CurlFormCode.Memory;
                        }
                    }
                    break;
                }

                // array case: already handled
                case CurlFormOption.Array:
                    if (aForms != null)
                    {
                        retCode = CurlFormCode.IllegalArray;
                    }
                    else
                    {
                        aForms = obj as CurlForms[];
                        if (aForms == null)
                        {
                            retCode = CurlFormCode.UnknownOption;
                        }
                    }
                    break;

                // slist
                case CurlFormOption.ContentHeader:
                {
                    aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    var s = obj as CurlSlist;
                    if (s == null)
                    {
                        retCode = CurlFormCode.UnknownOption;
                    }
                    else
                    {
                        aPointers[ptrArrayPos++] = s.Handle;
                    }
                    break;
                }

                // erroneous stuff
                case CurlFormOption.Nothing:
                    retCode = CurlFormCode.Incomplete;
                    break;

                // end
                case CurlFormOption.End:
                    if (aForms != null)     // end of form
                    {
                        aForms       = null;
                        formArrayPos = 0;
                    }
                    else
                    {
                        aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    }
                    break;

                // default is unknown
                default:
                    retCode = CurlFormCode.UnknownOption;
                    break;
                }
            }

            // ensure we didn't come up short on parameters
            if (ptrArrayPos != nRealCount)
            {
                retCode = CurlFormCode.Incomplete;
            }

            // if we're OK here, call into curl
            if (retCode == CurlFormCode.Ok)
            {
#if USE_LIBCURLSHIM
                retCode = (CurlFormCode)NativeMethods.curl_shim_formadd(_pItems, aPointers, nRealCount);
#else
                retCode = (CurlFormCode)NativeMethods.curl_formadd(ref _pItems[0], ref _pItems[1],
                                                                   (int)aPointers[0], aPointers[1],
                                                                   (int)aPointers[2], aPointers[3],
                                                                   (int)aPointers[4]);
#endif
            }

            // unmarshal native allocations
            for (var i = 0; i < nRealCount - 1; i += 2)
            {
                iCode = (CurlFormOption)(int)aPointers[i];
                switch (iCode)
                {
                case CurlFormOption.CopyName:
                case CurlFormOption.CopyContents:
                case CurlFormOption.FileContent:
                case CurlFormOption.File:
                case CurlFormOption.ContentType:
                case CurlFormOption.Filename:
                case CurlFormOption.Buffer:
                // byte buffer cases
                case CurlFormOption.PtrName:
                case CurlFormOption.PtrContents:
                case CurlFormOption.BufferPtr:
                {
                    if (aPointers[i + 1] != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(aPointers[i + 1]);
                    }
                    break;
                }

                default:
                    break;
                }
            }

            return(retCode);
        }