/// <summary> /// Constructor /// </summary> /// <exception cref="System.InvalidOperationException">This is thrown /// if <see cref="Curl"/> hasn't bee properly initialized.</exception> /// <exception cref="System.NullReferenceException">This is thrown if /// the native <c>CURL*</c> handle wasn't created successfully.</exception> public Easy() { Curl.EnsureCurl(); m_pCURL = External.curl_easy_init(); EnsureHandle(); External.curl_easy_setopt(m_pCURL, CURLoption.CURLOPT_NOPROGRESS, IntPtr.Zero); m_pMyStrings = External.curl_shim_alloc_strings(); m_pfWrite = null; m_privateData = null; m_writeData = null; m_pfRead = null; m_readData = null; m_pfProgress = null; m_progressData = null; m_pfDebug = null; m_debugData = null; m_pfHeader = null; m_headerData = null; m_pfSSLContext = null; m_sslContextData = null; m_pfIoctl = null; m_ioctlData = null; InstallDelegates(); }
/// <summary> /// Obtain status information for a Multi transfer. /// </summary> /// <returns> /// An array of <see cref="MultiInfo"/> objects, one for each /// <see cref="Easy"/> object child. /// </returns> /// <exception cref="System.NullReferenceException"> /// This is thrown if the native <c>Multi</c> handle wasn't /// created successfully. /// </exception> public MultiInfo[] InfoRead() { if (m_bGotMultiInfo) { return(m_multiInfo); } m_bGotMultiInfo = true; int nMsgs = 0; IntPtr pInfo = External.curl_shim_multi_info_read(m_pMulti, ref nMsgs); if (pInfo != IntPtr.Zero) { int msgSize = sizeof(Int32) * 2 + IntPtr.Size; m_multiInfo = new MultiInfo[nMsgs]; for (int i = 0; i < nMsgs; i++) { CURLMSG msg = (CURLMSG)Marshal.ReadInt32( pInfo, i * msgSize); IntPtr pEasy = Marshal.ReadIntPtr( pInfo, i * msgSize + sizeof(Int32)); CURLcode code = (CURLcode)Marshal.ReadInt32( pInfo, i * msgSize + sizeof(Int32) + IntPtr.Size); m_multiInfo[i] = new MultiInfo(msg, (Easy)m_htEasy[pEasy], code); } External.curl_shim_multi_info_free(pInfo); } return(m_multiInfo); }
/// <summary> /// Process-wide initialization -- call only once per process. /// </summary> /// <param name="flags">An or'd combination of /// <see cref="CURLinitFlag"/> members.</param> /// <returns>A <see cref="CURLcode"/>, hopefully /// <c>CURLcode.CURLE_OK</c>.</returns> public static CURLcode GlobalInit(int flags) { sm_curlCode = External.curl_global_init(flags); if (sm_curlCode == CURLcode.CURLE_OK) { External.curl_shim_initialize(); } return(sm_curlCode); }
/// <summary> /// Add an Easy object. /// </summary> /// <param name="easy"> /// <see cref="Easy"/> object to add. /// </param> /// <returns> /// A <see cref="CURLMcode"/>, hopefully <c>CURLMcode.CURLM_OK</c> /// </returns> /// <exception cref="System.NullReferenceException"> /// This is thrown if the native <c>Multi</c> handle wasn't /// created successfully. /// </exception> public CURLMcode AddHandle(Easy easy) { EnsureHandle(); IntPtr p = easy.GetHandle(); m_htEasy.Add(p, easy); return(External.curl_multi_add_handle(m_pMulti, easy.GetHandle())); }
/// <summary> /// URL decode a String. /// </summary> /// <param name="url">The string to URL decode.</param> /// <param name="length">Input string length; /// use 0 for cURL to determine.</param> /// <returns>A new URL decoded string.</returns> /// <exception cref="System.InvalidOperationException"> /// Thrown if cURL isn't properly initialized.</exception> public static string Unescape(string url, int length) { EnsureCurl(); IntPtr p = External.curl_unescape(url, length); String s = Marshal.PtrToStringAnsi(p); External.curl_free(p); return(s); }
/// <summary> /// Remove an Easy object. /// </summary> /// <param name="easy"> /// <see cref="Easy"/> object to remove. /// </param> /// <returns> /// A <see cref="CURLMcode"/>, hopefully <c>CURLMcode.CURLM_OK</c> /// </returns> /// <exception cref="System.NullReferenceException"> /// This is thrown if the native <c>Multi</c> handle wasn't /// created successfully. /// </exception> public CURLMcode RemoveHandle(Easy easy) { EnsureHandle(); IntPtr p = easy.GetHandle(); m_htEasy.Remove(p); return(External.curl_multi_remove_handle(m_pMulti, easy.GetHandle())); }
/// <summary> /// Process-wide cleanup -- call just before exiting process. /// </summary> /// <remarks> /// While it's not necessary that your program call this method /// before exiting, doing so will prevent leaks of native cURL resources. /// </remarks> public static void GlobalCleanup() { if (sm_curlCode == CURLcode.CURLE_OK) { External.curl_shim_cleanup(); External.curl_global_cleanup(); sm_curlCode = CURLcode.CURLE_FAILED_INIT; } }
private void InstallDelegates() { m_pDelLock = new External.CURLSH_LOCK_DELEGATE(LockDelegate); m_pDelUnlock = new External.CURLSH_UNLOCK_DELEGATE(UnlockDelegate); m_hThis = GCHandle.Alloc(this); m_ptrThis = (IntPtr)m_hThis; External.curl_shim_install_share_delegates(m_pShare, m_ptrThis, m_pDelLock, m_pDelUnlock); }
private External.CURLSH_UNLOCK_DELEGATE m_pDelUnlock; // unlock delegate /// <summary> /// Constructor /// </summary> /// <exception cref="System.InvalidOperationException">This is thrown /// if <see cref="Curl"/> hasn't bee properly initialized.</exception> /// <exception cref="System.NullReferenceException">This is thrown if /// the native <c>share</c> handle wasn't created successfully.</exception> public Share() { Curl.EnsureCurl(); m_pShare = External.curl_share_init(); EnsureHandle(); m_pfLock = null; m_pfUnlock = null; m_userData = null; InstallDelegates(); }
private void Dispose(bool disposing) { lock (this) { // no if (disposing) pattern to clean up managed objects if (m_pStringList != IntPtr.Zero) { External.curl_shim_free_slist(m_pStringList); m_pStringList = IntPtr.Zero; } } }
/// <summary> /// Constructor /// </summary> /// <exception cref="System.InvalidOperationException">This is thrown /// if <see cref="Curl"/> hasn't bee properly initialized.</exception> /// <exception cref="System.NullReferenceException"> /// This is thrown if the native <c>Multi</c> handle wasn't /// created successfully. /// </exception> public Multi() { Curl.EnsureCurl(); m_pMulti = External.curl_multi_init(); EnsureHandle(); m_fdSets = IntPtr.Zero; m_maxFD = 0; m_fdSets = External.curl_shim_alloc_fd_sets(); m_multiInfo = null; m_bGotMultiInfo = false; m_htEasy = new Hashtable(); }
private void Dispose(bool disposing) { lock (this) { // no if (disposing) pattern to clean up managed objects if (m_pItems[0] != IntPtr.Zero) { External.curl_formfree(m_pItems[0]); } m_pItems[0] = IntPtr.Zero; m_pItems[1] = IntPtr.Zero; } }
private void Dispose(bool disposing) { lock (this) { // if (disposing) cleanup managed objects if (m_pShare != IntPtr.Zero) { External.curl_shim_cleanup_share_delegates(m_pShare); External.curl_share_cleanup(m_pShare); m_hThis.Free(); m_ptrThis = IntPtr.Zero; m_pShare = IntPtr.Zero; } } }
/// <summary> /// Set options for this object. /// </summary> /// <param name="option"> /// One of the values in the <see cref="CURLSHoption"/> /// enumeration. /// </param> /// <param name="parameter"> /// An appropriate object based on the value passed in the /// <c>option</c> argument. See <see cref="CURLSHoption"/> /// for more information about the appropriate parameter type. /// </param> /// <returns> /// A <see cref="CURLSHcode"/>, hopefully /// <c>CURLSHcode.CURLSHE_OK</c>. /// </returns> /// <exception cref="System.NullReferenceException">This is thrown if /// the native <c>share</c> handle wasn't created successfully.</exception> public CURLSHcode SetOpt(CURLSHoption option, Object parameter) { EnsureHandle(); CURLSHcode retCode = CURLSHcode.CURLSHE_OK; switch (option) { case CURLSHoption.CURLSHOPT_LOCKFUNC: LockFunction lf = parameter as LockFunction; if (lf == null) { return(CURLSHcode.CURLSHE_BAD_OPTION); } m_pfLock = lf; break; case CURLSHoption.CURLSHOPT_UNLOCKFUNC: UnlockFunction ulf = parameter as UnlockFunction; if (ulf == null) { return(CURLSHcode.CURLSHE_BAD_OPTION); } m_pfUnlock = ulf; break; case CURLSHoption.CURLSHOPT_SHARE: case CURLSHoption.CURLSHOPT_UNSHARE: { CURLlockData opt = (CURLlockData) Convert.ToInt32(parameter); if ((opt != CURLlockData.CURL_LOCK_DATA_COOKIE) && (opt != CURLlockData.CURL_LOCK_DATA_DNS)) { return(CURLSHcode.CURLSHE_BAD_OPTION); } retCode = External.curl_share_setopt(m_pShare, option, (IntPtr)opt); break; } case CURLSHoption.CURLSHOPT_USERDATA: m_userData = parameter; break; default: retCode = CURLSHcode.CURLSHE_BAD_OPTION; break; } return(retCode); }
private Easy(Easy from) { m_pCURL = External.curl_easy_duphandle(from.m_pCURL); EnsureHandle(); m_pMyStrings = External.curl_shim_alloc_strings(); m_pfWrite = null; m_privateData = null; m_writeData = null; m_pfRead = null; m_readData = null; m_pfProgress = null; m_progressData = null; m_pfDebug = null; m_debugData = null; m_pfHeader = null; m_headerData = null; m_pfSSLContext = null; m_sslContextData = null; m_pfIoctl = null; m_ioctlData = null; InstallDelegates(); }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> /// <param name="disposing"><c>true</c> if managed resources should be disposed.</param> protected virtual void Dispose(bool disposing) { if (!disposed) { lock (this) { // if (disposing) // managed member cleanup // unmanaged cleanup if (m_pMulti != IntPtr.Zero) { External.curl_multi_cleanup(m_pMulti); m_pMulti = IntPtr.Zero; } if (m_fdSets != IntPtr.Zero) { External.curl_shim_free_fd_sets(m_fdSets); m_fdSets = IntPtr.Zero; } } disposed = true; } }
/// <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); }
/// <summary> /// Append a string to the list. /// </summary> /// <param name="str">The <c>string</c> to append.</param> public void Append(string str) { m_pStringList = External.curl_shim_add_string_to_slist( m_pStringList, str); }