コード例 #1
1
ファイル: qc.cs プロジェクト: bluejack2000/core
        public static bool gopost(string url, string user, string password,  string data, TradeLink.API.DebugDelegate deb, out string result)
        {
            debs = deb;
            Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);

            Easy easy = new Easy();
            rresult = new StringBuilder();
            hasresult = false;

            Easy.WriteFunction wf = new Easy.WriteFunction(OnWritePostData);
            easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, wf);
            Easy.DebugFunction df = new Easy.DebugFunction(OnDebug);
            easy.SetOpt(CURLoption.CURLOPT_DEBUGFUNCTION, df);

            // simple post - with a string
            easy.SetOpt(CURLoption.CURLOPT_POSTFIELDS,
                data);
            Slist sl = new Slist();
            sl.Append("Content-Type:application/xml");
            sl.Append("Accept: application/xml");
            easy.SetOpt(CURLoption.CURLOPT_HTTPHEADER, sl);
            easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, false);
            easy.SetOpt(CURLoption.CURLOPT_USERAGENT,
                "Mozilla 4.0 (compatible; MSIE 6.0; Win32");
            easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, true);
            easy.SetOpt(CURLoption.CURLOPT_USERPWD, user + ":" + password);
            CURLhttpAuth authflag = CURLhttpAuth.CURLAUTH_BASIC;
            easy.SetOpt(CURLoption.CURLOPT_HTTPAUTH, authflag);
            easy.SetOpt(CURLoption.CURLOPT_URL,url);
            
            easy.SetOpt(CURLoption.CURLOPT_POST, true);
            if (debs!=null)
                easy.SetOpt(CURLoption.CURLOPT_VERBOSE, true);
            


            CURLcode err = easy.Perform();
            int waits = 0;
            int maxwaits = 200;
            while (!hasresult && (waits++<maxwaits))
                System.Threading.Thread.Sleep(10);

            int rcodei = 0;
            CURLcode rcode = easy.GetInfo(CURLINFO.CURLINFO_RESPONSE_CODE, ref rcodei);


            if (!hasresult && (deb != null))
                deb(easy.StrError(err));

            easy.Cleanup();



            Curl.GlobalCleanup();
            result = rresult.ToString();



            return hasresult;
        }
コード例 #2
0
        /// <summary>
        /// Extract <c>Slist</c> information from an <c>Easy</c> object.
        /// </summary>
        /// <param name="info">One of the values in the
        /// <see cref="CURLINFO"/> enumeration. In this case, it must
        /// specifically be one of the members that obtains an <c>Slist</c>.
        /// </param>
        /// <param name="slist">Reference to an <c>Slist</c> value.</param>
        /// <returns>The <see cref="CURLcode"/> obtained from the internal
        /// call to <c>curl_easy_getinfo()</c>.
        /// </returns>
        /// <exception cref="System.NullReferenceException">This is thrown if
        /// the native <c>CURL*</c> handle wasn't created successfully.</exception>
        public CURLcode GetInfo(CURLINFO info, ref Slist slist)
        {
            EnsureHandle();
            CURLcode retCode = CURLcode.CURLE_OK;
            IntPtr   ptr = IntPtr.Zero, ptrs = IntPtr.Zero;

            if ((int)info < CURLINFO_SLIST)
            {
                return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
            }
            retCode = External.curl_easy_getinfo_ptr(m_pCURL, info, ref ptr);
            if (retCode != CURLcode.CURLE_OK)
            {
                return(retCode);
            }
            slist = new Slist();
            while (ptr != IntPtr.Zero)
            {
                ptr = External.curl_shim_get_string_from_slist(
                    ptr, ref ptrs);
                slist.Append(Marshal.PtrToStringAnsi(ptrs));
            }
            return(retCode);
        }
コード例 #3
0
        /// <summary>
        /// Set options for this object. See the <c>EasyGet</c> sample for
        /// basic usage.
        /// </summary>
        /// <param name="option">This should be a valid <see cref="CURLoption"/>.</param>
        /// <param name="parameter">This should be a parameter of a varying
        /// type based on the value of the <c>option</c> parameter.</param>
        /// <exception cref="System.NullReferenceException">This is thrown if
        /// the native <c>CURL*</c> handle wasn't created successfully.</exception>
        /// <returns>A <see cref="CURLcode"/>, typically obtained from
        /// <c>cURL</c> internally, but sometimes a
        /// <see cref="CURLcode.CURLE_BAD_FUNCTION_ARGUMENT"/>
        /// will be returned if the type of value of <c>parameter</c> is invalid.
        /// </returns>
        public CURLcode SetOpt(CURLoption option, Object parameter)
        {
            EnsureHandle();
            CURLcode retCode = CURLcode.CURLE_OK;

            // numeric cases
            if ((int)option < CURLOPTTYPE_OBJECTPOINT)
            {
                int i = 0;
                if (option == CURLoption.CURLOPT_DNS_USE_GLOBAL_CACHE ||
                    option == CURLoption.CURLOPT_SOURCE_PORT)
                {
                    return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                }
                else if (option == CURLoption.CURLOPT_TIMEVALUE)
                {
                    // unboxing may throw class cast exception
                    //DateTime d = (DateTime)parameter;
                    DateTime startTime = Main.DateTimeBegin;
                    TimeSpan currTime  = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
                    i = Convert.ToInt32(currTime.TotalSeconds);
                }
                else
                {
                    i = Convert.ToInt32(parameter);
                }

                retCode = External.curl_easy_setopt_int(m_pCURL,
                                                        option, i);
            }

            // object cases: the majority
            else if ((int)option < CURLOPTTYPE_FUNCTIONPOINT)
            {
                switch (option)
                {
                // various data items
                case CURLoption.CURLOPT_PRIVATE:
                    m_privateData = parameter; break;

                case CURLoption.CURLOPT_WRITEDATA:
                    m_writeData = parameter; break;

                case CURLoption.CURLOPT_READDATA:
                    m_readData = parameter; break;

                case CURLoption.CURLOPT_PROGRESSDATA:
                    m_progressData = parameter; break;

                case CURLoption.CURLOPT_DEBUGDATA:
                    m_debugData = parameter; break;

                case CURLoption.CURLOPT_HEADERDATA:
                    m_headerData = parameter; break;

                case CURLoption.CURLOPT_SSL_CTX_DATA:
                    m_sslContextData = parameter; break;

                case CURLoption.CURLOPT_IOCTLDATA:
                    m_ioctlData = parameter; break;

                // items that can't be set externally or
                // obsolete items
                case CURLoption.CURLOPT_ERRORBUFFER:
                case CURLoption.CURLOPT_STDERR:
                case CURLoption.CURLOPT_SOURCE_HOST:
                case CURLoption.CURLOPT_SOURCE_PATH:
                case CURLoption.CURLOPT_PASV_HOST:
                    return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);

                // singular case for share
                case CURLoption.CURLOPT_SHARE:
                {
                    Share share = parameter as Share;
                    if (share == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    retCode = External.curl_easy_setopt_ptr(m_pCURL,
                                                            option, share.GetHandle());
                    break;
                }

                // multipart HTTP post
                case CURLoption.CURLOPT_HTTPPOST:
                {
                    MultiPartForm mf = parameter as MultiPartForm;
                    if (mf == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    retCode = External.curl_easy_setopt_ptr(m_pCURL,
                                                            option, mf.GetHandle());
                    break;
                }

                // items curl wants as a curl_slist
                case CURLoption.CURLOPT_HTTPHEADER:
                case CURLoption.CURLOPT_PREQUOTE:
                case CURLoption.CURLOPT_QUOTE:
                case CURLoption.CURLOPT_POSTQUOTE:
                case CURLoption.CURLOPT_SOURCE_QUOTE:
                case CURLoption.CURLOPT_TELNETOPTIONS:
                case CURLoption.CURLOPT_HTTP200ALIASES:
                {
                    Slist slist = parameter as Slist;
                    if (slist == null)
                    {
                        retCode = External.curl_easy_setopt_ptr(m_pCURL,
                                                                option, IntPtr.Zero);
                    }
                    else
                    {
                        retCode = External.curl_easy_setopt_ptr(m_pCURL,
                                                                option, slist.GetHandle());
                    }
                    break;
                }

                // string items
                default:
                {
                    string s = parameter as string;
                    if (s == null)
                    {
                        retCode = External.curl_easy_setopt_ptr(m_pCURL,
                                                                option, IntPtr.Zero);
                    }
                    else
                    {
                        IntPtr pCurlStr = External.curl_shim_add_string(
                            m_pMyStrings, s);
                        if (pCurlStr != IntPtr.Zero)
                        {
                            retCode = External.curl_easy_setopt_ptr(m_pCURL,
                                                                    option, pCurlStr);
                        }
                    }
                    break;
                }
                }
            }

            // FUNCTIONPOINT args, for delegates
            else if ((int)option < CURLOPTTYPE_OFF_T)
            {
                switch (option)
                {
                case CURLoption.CURLOPT_WRITEFUNCTION:
                {
                    WriteFunction wf = parameter as WriteFunction;
                    if (wf == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfWrite = wf;
                    break;
                }

                case CURLoption.CURLOPT_READFUNCTION:
                {
                    ReadFunction rf = parameter as ReadFunction;
                    if (rf == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfRead = rf;
                    break;
                }

                case CURLoption.CURLOPT_PROGRESSFUNCTION:
                {
                    ProgressFunction pf = parameter as ProgressFunction;
                    if (pf == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfProgress = pf;
                    break;
                }

                case CURLoption.CURLOPT_DEBUGFUNCTION:
                {
                    DebugFunction pd = parameter as DebugFunction;
                    if (pd == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfDebug = pd;
                    break;
                }

                case CURLoption.CURLOPT_HEADERFUNCTION:
                {
                    HeaderFunction hf = parameter as HeaderFunction;
                    if (hf == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfHeader = hf;
                    break;
                }

                case CURLoption.CURLOPT_SSL_CTX_FUNCTION:
                {
                    SSLContextFunction sf = parameter as SSLContextFunction;
                    if (sf == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfSSLContext = sf;
                    break;
                }

                case CURLoption.CURLOPT_IOCTLFUNCTION:
                {
                    IoctlFunction iof = parameter as IoctlFunction;
                    if (iof == null)
                    {
                        return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                    }
                    m_pfIoctl = iof;
                    break;
                }

                default:
                    return(CURLcode.CURLE_BAD_FUNCTION_ARGUMENT);
                }
            }

            // otherwise, it's one of those 64-bit off_t guys!
            else
            {
                Int64 i = Convert.ToInt64(parameter);
                retCode = External.curl_easy_setopt_int64(m_pCURL,
                                                          option, i);
            }

            return(retCode);
        }
コード例 #4
0
ファイル: qc.cs プロジェクト: bluejack2000/core
        public static bool gomultipartpost(string url, string user, string password, string fname, string fpath, int ticketid,int maxwaitsec, bool showprogress, TradeLink.API.DebugDelegate deb, out string result)
        {
            debs = deb;
            Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);

            Easy easy = new Easy();
            rresult = new StringBuilder();
            hasresult = false;

            MultiPartForm mf = new MultiPartForm();


            // <input name="frmFileOrigPath">
            mf.AddSection(CURLformoption.CURLFORM_COPYNAME, "document[name]",
                CURLformoption.CURLFORM_COPYCONTENTS, fname,
                CURLformoption.CURLFORM_END);



            // <input type="File" name="f1">
            mf.AddSection(CURLformoption.CURLFORM_COPYNAME, "document[file]",
                CURLformoption.CURLFORM_FILE, fpath,
                CURLformoption.CURLFORM_CONTENTTYPE, "application/octet-stream",
                CURLformoption.CURLFORM_END);

            // <input name="frmFileDate">
            if (ticketid != 0)
                mf.AddSection(CURLformoption.CURLFORM_COPYNAME, "document[ticket_id]",
                    CURLformoption.CURLFORM_COPYCONTENTS, ticketid.ToString(),
                    CURLformoption.CURLFORM_END);

            if (showprogress)
            {
                Easy.ProgressFunction pf = new Easy.ProgressFunction(OnProgress);
                easy.SetOpt(CURLoption.CURLOPT_PROGRESSFUNCTION, pf);
            }


            Easy.WriteFunction wf = new Easy.WriteFunction(OnWritePostData);
            easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, wf);
            easy.SetOpt(CURLoption.CURLOPT_HTTPPOST, mf);
            Easy.DebugFunction df = new Easy.DebugFunction(OnDebug);
            easy.SetOpt(CURLoption.CURLOPT_DEBUGFUNCTION, df);

            // simple post - with a string
            //easy.SetOpt(CURLoption.CURLOPT_POSTFIELDS,data);
            Slist sl = new Slist();
            //sl.Append("Content-Type:multipart/form-data");
            sl.Append("Accept: application/xml");
            easy.SetOpt(CURLoption.CURLOPT_HTTPHEADER, sl);
            easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, false);
            easy.SetOpt(CURLoption.CURLOPT_USERAGENT,
                "Mozilla 4.0 (compatible; MSIE 6.0; Win32");
            easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, true);
            easy.SetOpt(CURLoption.CURLOPT_USERPWD, user + ":" + password);
            CURLhttpAuth authflag = CURLhttpAuth.CURLAUTH_BASIC;
            easy.SetOpt(CURLoption.CURLOPT_HTTPAUTH, authflag);
            easy.SetOpt(CURLoption.CURLOPT_URL, url);

            //easy.SetOpt(CURLoption.CURLOPT_POST, true);
            if (debs != null)
                easy.SetOpt(CURLoption.CURLOPT_VERBOSE, true);



            CURLcode err = easy.Perform();
            int waits = 0;
            int maxwaits = 100*maxwaitsec;
            while (!hasresult && (waits++ < maxwaits))
                System.Threading.Thread.Sleep(10);

            int rcodei = 0;
            CURLcode rcode = easy.GetInfo(CURLINFO.CURLINFO_RESPONSE_CODE, ref rcodei);


            if (!hasresult && (deb != null))
                deb(easy.StrError(err));

            easy.Cleanup();
            mf.Free();


            Curl.GlobalCleanup();
            result = rresult.ToString();



            return hasresult && (rcodei==201);
        }
コード例 #5
0
ファイル: Easy.cs プロジェクト: bossaia/alexandrialibrary
        /// <summary>
        /// Extract <c>Slist</c> information from an <c>Easy</c> object.
        /// </summary>
        /// <param name="info">One of the values in the
        /// <see cref="CURLINFO"/> enumeration. In this case, it must
        /// specifically be one of the members that obtains an <c>Slist</c>.
        /// </param>
        /// <param name="slist">Reference to an <c>Slist</c> value.</param>
        /// <returns>The <see cref="CURLcode"/> obtained from the internal
        /// call to <c>curl_easy_getinfo()</c>.
        /// </returns>
        /// <exception cref="System.NullReferenceException">This is thrown if
        /// the native <c>CURL*</c> handle wasn't created successfully.</exception>
        public CURLcode GetInfo(CURLINFO info, ref Slist slist)
        {
            EnsureHandle();
            CURLcode retCode = CURLcode.CURLE_OK;
            IntPtr ptr = IntPtr.Zero, ptrs = IntPtr.Zero;

            if ((int)info < CURLINFO_SLIST)
                return CURLcode.CURLE_BAD_FUNCTION_ARGUMENT;
            retCode = External.curl_easy_getinfo(m_pCURL, info, ref ptr);
            if (retCode != CURLcode.CURLE_OK)
                return retCode;
            slist = new Slist();
            while (ptr != IntPtr.Zero)
            {
                ptr = External.curl_shim_get_string_from_slist(
                    ptr, ref ptrs);
                slist.Append(Marshal.PtrToStringAnsi(ptrs));
            }
            return retCode;
        }
コード例 #6
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.CURL_FORMADD_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>MultiPartForm.AddSection(option1, value1, ..., optionX, valueX,
        /// CURLformoption.CURLFORM_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>CURLFORM_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)
        {
            int          nCount     = args.Length;
            int          nRealCount = nCount;
            CURLFORMcode retCode    = CURLFORMcode.CURL_FORMADD_OK;

            CurlForms[] aForms = null;

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

            // ensure the last argument is CURLFORM_END
            CURLformoption iCode = (CURLformoption)
                                   Convert.ToInt32(args.GetValue(nCount - 1));

            if (iCode != CURLformoption.CURLFORM_END)
            {
                return(CURLFORMcode.CURL_FORMADD_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 CURLFORM_END
            for (int i = 0; i < nCount; i += 2)
            {
                iCode = (CURLformoption)Convert.ToInt32(args.GetValue(i));
                switch (iCode)
                {
                case CURLformoption.CURLFORM_ARRAY:
                {
                    aForms = args.GetValue(i + 1) as CurlForms[];
                    if (aForms == null)
                    {
                        return(CURLFORMcode.CURL_FORMADD_INCOMPLETE);
                    }
                    int nFormsCount = aForms.Length;
                    for (int j = 0; j < nFormsCount; j++)
                    {
                        CurlForms pcf = aForms.GetValue(j) as CurlForms;
                        if (pcf == null)
                        {
                            return(CURLFORMcode.CURL_FORMADD_INCOMPLETE);
                        }
                        if (j == nFormsCount - 1)
                        {
                            if (pcf.opt != CURLformoption.CURLFORM_END)
                            {
                                return(CURLFORMcode.CURL_FORMADD_INCOMPLETE);
                            }
                        }
                        else
                        {
                            if (pcf.opt == CURLformoption.CURLFORM_END)
                            {
                                return(CURLFORMcode.CURL_FORMADD_INCOMPLETE);
                            }
                        }
                    }
                    // -2 accounts for the fact that we're a) not
                    // including the item with CURLFORM_END and b) not
                    // including CURLFORM_ARRAY in what we pass to cURL
                    nRealCount += 2 * (nFormsCount - 2);
                    break;
                }

                default:
                    break;
                }
            }

            // allocate the IntPtr array for the data
            IntPtr[] aPointers = new IntPtr[nRealCount];
            for (int i = 0; i < nRealCount - 1; i++)
            {
                aPointers[i] = IntPtr.Zero;
            }
            aPointers[nRealCount - 1] = (IntPtr)CURLformoption.CURLFORM_END;

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

            while ((retCode == CURLFORMcode.CURL_FORMADD_OK) &&
                   (ptrArrayPos < nRealCount))
            {
                if (aForms != null)
                {
                    CurlForms pcf = aForms.GetValue(formArrayPos++)
                                    as CurlForms;
                    if (pcf == null)
                    {
                        retCode = CURLFORMcode.CURL_FORMADD_UNKNOWN_OPTION;
                        break;
                    }
                    iCode = pcf.opt;
                    obj   = pcf.val;
                }
                else
                {
                    iCode = (CURLformoption)Convert.ToInt32(
                        args.GetValue(argArrayPos++));
                    obj = (iCode == CURLformoption.CURLFORM_END) ? null :
                          args.GetValue(argArrayPos++);
                }

                switch (iCode)
                {
                // handle byte-array pointer-related items
                case CURLformoption.CURLFORM_PTRNAME:
                case CURLformoption.CURLFORM_PTRCONTENTS:
                case CURLformoption.CURLFORM_BUFFERPTR:
                {
                    byte[] bytes = obj as byte[];
                    if (bytes == null)
                    {
                        retCode = CURLFORMcode.CURL_FORMADD_UNKNOWN_OPTION;
                    }
                    else
                    {
                        int    nLen = bytes.Length;
                        IntPtr ptr  = Marshal.AllocHGlobal(nLen);
                        if (ptr != IntPtr.Zero)
                        {
                            aPointers[ptrArrayPos++] = (IntPtr)iCode;
                            // copy bytes to unmanaged buffer
                            for (int j = 0; j < nLen; j++)
                            {
                                Marshal.WriteByte(ptr, bytes[j]);
                            }
                            aPointers[ptrArrayPos++] = ptr;
                        }
                        else
                        {
                            retCode = CURLFORMcode.CURL_FORMADD_MEMORY;
                        }
                    }
                    break;
                }

                // length values
                case CURLformoption.CURLFORM_NAMELENGTH:
                case CURLformoption.CURLFORM_CONTENTSLENGTH:
                case CURLformoption.CURLFORM_BUFFERLENGTH:
                    aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    aPointers[ptrArrayPos++] = (IntPtr)
                                               Convert.ToInt32(obj);
                    break;

                // strings
                case CURLformoption.CURLFORM_COPYNAME:
                case CURLformoption.CURLFORM_COPYCONTENTS:
                case CURLformoption.CURLFORM_FILECONTENT:
                case CURLformoption.CURLFORM_FILE:
                case CURLformoption.CURLFORM_CONTENTTYPE:
                case CURLformoption.CURLFORM_FILENAME:
                case CURLformoption.CURLFORM_BUFFER:
                {
                    aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    string s = obj as String;
                    if (s == null)
                    {
                        retCode = CURLFORMcode.CURL_FORMADD_UNKNOWN_OPTION;
                    }
                    else
                    {
                        IntPtr p = Marshal.StringToHGlobalAnsi(s);
                        if (p != IntPtr.Zero)
                        {
                            aPointers[ptrArrayPos++] = p;
                        }
                        else
                        {
                            retCode = CURLFORMcode.CURL_FORMADD_MEMORY;
                        }
                    }
                    break;
                }

                // array case: already handled
                case CURLformoption.CURLFORM_ARRAY:
                    if (aForms != null)
                    {
                        retCode = CURLFORMcode.CURL_FORMADD_ILLEGAL_ARRAY;
                    }
                    else
                    {
                        aForms = obj as CurlForms[];
                        if (aForms == null)
                        {
                            retCode = CURLFORMcode.CURL_FORMADD_UNKNOWN_OPTION;
                        }
                    }
                    break;

                // slist
                case CURLformoption.CURLFORM_CONTENTHEADER:
                {
                    aPointers[ptrArrayPos++] = (IntPtr)iCode;
                    Slist s = obj as Slist;
                    if (s == null)
                    {
                        retCode = CURLFORMcode.CURL_FORMADD_UNKNOWN_OPTION;
                    }
                    else
                    {
                        aPointers[ptrArrayPos++] = s.GetHandle();
                    }
                    break;
                }

                // erroneous stuff
                case CURLformoption.CURLFORM_NOTHING:
                    retCode = CURLFORMcode.CURL_FORMADD_INCOMPLETE;
                    break;

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

                // default is unknown
                default:
                    retCode = CURLFORMcode.CURL_FORMADD_UNKNOWN_OPTION;
                    break;
                }
            }

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

            // if we're OK here, call into curl
            if (retCode == CURLFORMcode.CURL_FORMADD_OK)
            {
                retCode = (CURLFORMcode)External.curl_shim_formadd(
                    m_pItems, aPointers, nRealCount);
            }

            // unmarshal native allocations
            for (int i = 0; i < nRealCount - 1; i += 2)
            {
                iCode = (CURLformoption)(int)aPointers[i];
                switch (iCode)
                {
                case CURLformoption.CURLFORM_COPYNAME:
                case CURLformoption.CURLFORM_COPYCONTENTS:
                case CURLformoption.CURLFORM_FILECONTENT:
                case CURLformoption.CURLFORM_FILE:
                case CURLformoption.CURLFORM_CONTENTTYPE:
                case CURLformoption.CURLFORM_FILENAME:
                case CURLformoption.CURLFORM_BUFFER:
                // byte buffer cases
                case CURLformoption.CURLFORM_PTRNAME:
                case CURLformoption.CURLFORM_PTRCONTENTS:
                case CURLformoption.CURLFORM_BUFFERPTR:
                {
                    if (aPointers[i + 1] != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(aPointers[i + 1]);
                    }
                    break;
                }

                default:
                    break;
                }
            }

            return(retCode);
        }