private void RawCreateDirectory(string path) { int index = path.LastIndexOf("/", StringComparison.OrdinalIgnoreCase); if (index == -1) { path = "/" + path; index = 0; } string baseDir = path.Substring(0, index); string dirName = path.Substring(index + 1); bool pushedBaseDir = false; if (baseDir.Trim() != String.Empty) //fix bug 4886 { pushedBaseDir = pushDirectory(baseDir); if (!pushedBaseDir) { RawCreateDirectory(baseDir); ValidateFTPCommand(pushDirectory(baseDir)); ////fix bug 4886 - avoid stackoverflow if directory was not properly pushed. pushedBaseDir = true; } } ValidateFTPCommand(WinInet.FtpCreateDirectory(m_hFtp, dirName)); if (pushedBaseDir) { popDirectory(); } }
/// <summary> /// Begins an asynchronous request /// </summary> /// <param name="useCache">true to use cache, otherwise false</param> /// <param name="timeOut">timeout, in milliseconds</param> public void StartRequest(CacheSettings cacheSettings, int timeOut) { requestRunning = true; // Check the cache if (cacheSettings != CacheSettings.NOCACHE) { Internet_Cache_Entry_Info cacheInfo; if (WinInet.GetUrlCacheEntryInfo(m_url, out cacheInfo)) { ResponseStream = new FileStream(cacheInfo.lpszLocalFileName, FileMode.Open, FileAccess.Read); FireRequestComplete(); } } // Make an async request if (ResponseStream == null && cacheSettings != CacheSettings.CACHEONLY) { try { m_webRequest = HttpRequestHelper.CreateHttpWebRequest(m_url, true); } catch (InvalidCastException) { m_webRequest = WebRequest.Create(m_url); } m_webRequest.Timeout = timeOut; m_webRequest.BeginGetResponse(new AsyncCallback(RequestCompleteHandler), new object()); } }
/// <summary> /// List the files in the specified directory. /// </summary> /// <param name="path"></param> /// <returns></returns> public override string[] ListFiles(string path) { path = CombinePath(m_path, path); if (!path.EndsWith("/", StringComparison.OrdinalIgnoreCase)) { path += "/"; } ArrayList dirList = new ArrayList(); //note: some FTP servers have problems listing directories with spaces in them, //so we need to change the directory and then do a simple listing instead if (pushDirectory(path)) { try { Win32_Find_Data[] findData = WinInet.FtpFind(m_hFtp, "*.*"); for (int i = 0; i < findData.Length; i++) { if ((findData[i].dwFileAttributes & (int)FileAttributes.Directory) == 0) { dirList.Add(findData[i].cFileName); } } } finally { popDirectory(); } } return((string[])ArrayHelper.CollectionToArray(dirList, typeof(string))); }
/// <summary> /// This method is called to determine whether a file exists. /// </summary> /// <param name="path">The file</param> /// <returns>true indicates the file exists, false indicates it doesn't</returns> override public bool FileExists(string path) { path = CombinePath(m_path, path); string fname = path; string dir = ""; int index = path.LastIndexOf("/", StringComparison.OrdinalIgnoreCase); if (index != -1) { fname = path.Substring(index + 1); dir = path.Substring(0, index); } if (pushDirectory(dir)) { try { Win32_Find_Data[] files = WinInet.FtpFind(m_hFtp, fname); if (files.Length > 0) { return(true); } } finally { popDirectory(); } } return(false); }
/// <summary> /// Pops a directory change off of the stack and returns to the previous working directory. /// </summary> private void popDirectory() { string currPath = (string)pathStack.Pop(); string newPath = pathStack.Count > 0 ? (string)pathStack.Peek() : m_path; if (!currPath.Equals(newPath))//This optimization prevents needless CWD network I/O. { WinInet.FtpSetCurrentDirectory(m_hFtp, newPath); } }
/// <summary> /// Disconnect from the FTP Server /// </summary> /// <returns>true if disconnected succeeded, otherwise false</returns> public override void Disconnect() { // Close the handles if (!WinInet.InternetCloseHandle(m_hFtp)) { // ignore as this can commonly happen if the connection //was never properly established } else if (!WinInet.InternetCloseHandle(m_hInternet)) { // If the handles didn't close, this is very unexpected and bad Debug.Assert(false, "Disconnect couldn't close the Internet handle in " + GetType().ToString()); } }
/// <summary> /// Copy a file to the FTP destination /// </summary> /// <param name="from">The path from which to copy the file</param> /// <param name="to">The file to which to copy the file</param> /// <param name="overWrite">Ignored- files are always overwritten on the FTP server</param> /// <returns>true if the copy succeeded, otherwise false</returns> public override bool CopyFile(string from, string to, bool overWrite) { // Validate that the file transferred, throw an exception if necessary // Non fatal errors will allow putFile = false to pass through without // throwing an exception. That will pass that CopyFile failed up // up the chain, allowing any retry logic to execute. // NOTE: This should respect the bool overWrite. Right now, it just // blows over the top return(ValidateFileTransfer(WinInet.FtpPutFile( m_hFtp, from, to, 0, // FTP Flags (none necessary) 0 // Application Context ))); }
/// <summary> /// Pushes a directory change onto the stack if a directory change is successful. /// This operation should be used to change directories because some FTP server /// behave strangely when performing operations outside of the target directory. /// This stack behavior makes it very easy for operations to transparently change /// directories and then return to the previous directory. /// </summary> /// <param name="path">the directory to change to</param> /// <returns>true if the directory change was successful</returns> private bool pushDirectory(string path) { Trace.Assert(path.StartsWith(PathDelimiter, StringComparison.OrdinalIgnoreCase), "pushDirectory called with an unexpected (relative) path: " + path); if (pathStack.Count > 0 && pathStack.Peek().Equals(path)) { //then we're already in the specified directory, so just push //the directory onto the stack and return true. //This optimization prevents needless CWD network I/O. pathStack.Push(path); return(true); } bool success = WinInet.FtpSetCurrentDirectory(m_hFtp, path); if (success) { pathStack.Push(path); } return(success); }
private static bool CallInternetSetOption(InternetPerConnectionOption[] options) { var optionList = new InternetPerConnectionOptionList(); optionList.size = Marshal.SizeOf(optionList); optionList.connection = IntPtr.Zero; //Default Connection optionList.optionCount = options.Length; optionList.optionError = 0; optionList.options = VarPtr(options); var optionListSize = Marshal.SizeOf(optionList); var optionListPtr = Marshal.AllocCoTaskMem(optionListSize); Marshal.StructureToPtr(optionList, optionListPtr, true); bool iReturn; iReturn = WinInet.InternetSetOption(IntPtr.Zero, (int)InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, optionListPtr, Marshal.SizeOf(optionList)); if (iReturn == false) { var exception = new Win32Exception(Marshal.GetLastWin32Error()); throw exception; } iReturn = InternetOptionSettingsChanged(); //if (iReturn == true) //{ // iReturn = InternetOptionRefresh(); //} // free the COM memory Marshal.FreeCoTaskMem(optionListPtr); return(iReturn); }
/// <summary> /// Throws the correct Site Destination exception for a given WinInet Error Code. /// This attempts to map common WinInet errors to corresponding Destination errors. /// </summary> /// <param name="error">The WinInet error code</param> private void ThrowDestinationException(int error) { // Exception detail data string exceptionType = null; string extendedMessage = WinInet.GetExtendedInfo(); if (extendedMessage == null || extendedMessage == String.Empty) { extendedMessage = "The source of the error is unknown."; } SiteDestinationException exception = null; // This wraps the lower level WinInet errors into higher level // Site destination exceptions. It also gathers extended info from // the connection to assist with troubleshooting. switch (error) { case ERROR_INTERNET.CANNOT_CONNECT: exceptionType = SiteDestinationException.ConnectionException; break; case ERROR_INTERNET.NAME_NOT_RESOLVED: exceptionType = SiteDestinationException.ConnectionException; break; case ERROR_INTERNET.ITEM_NOT_FOUND: exceptionType = SiteDestinationException.TransferException; break; case ERROR_INTERNET.TIMEOUT: exceptionType = SiteDestinationException.TransferException; break; case ERROR_INTERNET.LOGIN_FAILURE: exception = new LoginException(null, error); break; case ERROR_INTERNET.INCORRECT_PASSWORD: exception = new LoginException(null, error); break; case ERROR_INTERNET.INCORRECT_USER_NAME: exception = new LoginException(null, error); break; case ERROR_INTERNET.EXTENDED_ERROR: exceptionType = SiteDestinationException.UnexpectedException; break; default: exceptionType = SiteDestinationException.UnexpectedException; break; } // Set up a sitedestination exception with the correct information if (exception == null) { exception = new SiteDestinationException( null, exceptionType, GetType().Name, error); } exception.DestinationErrorCode = error; exception.DestinationType = GetType().Name; exception.DestinationExtendedMessage = extendedMessage; // throw it throw exception; }
public static bool InternetOptionRefresh() { return(WinInet.InternetSetOption(IntPtr.Zero, (int)InternetOption.INTERNET_OPTION_REFRESH, IntPtr.Zero, 0)); }
/// <summary> /// Deletes a file on the FTP server /// </summary> /// <param name="path">The path of the file to delete (typically /// relative to the current directory)</param> public override void DeleteFile(string path) { path = CombinePath(m_path, path); ValidateFTPCommand(WinInet.FtpDeleteFile(m_hFtp, path)); }
public string getCurrentDirectory() { return(WinInet.GetFtpCurrentDirectory(m_hFtp)); }
/// <summary> /// ネットワークに接続できるか試みます /// </summary> /// <returns>true = 接続可能 / false = 接続不可</returns> public static bool isAliveNetwork() { int inetFlg; return(WinInet.InternetGetConnectedState(out inetFlg, 0)); }
public static bool InternetOptionSettingsChanged() { return(WinInet.InternetSetOption(IntPtr.Zero, (int)InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0)); }
/// <summary> /// Retrieves a file from the destination location. /// </summary> /// <param name="RemotePath">The path of the file to get from the FTP server</param> /// <param name="LocalFile">The path of the local file to copy the file contents to</param> /// <param name="isBinary">True if the remote file is binary</param> override public bool GetFile(String RemotePath, string LocalFile, bool isBinary) { uint dwFlags = isBinary ? INTERNET_FLAG.TRANSFER_BINARY : INTERNET_FLAG.TRANSFER_ASCII; return(WinInet.FtpGetFile(m_hFtp, RemotePath, LocalFile, false, (int)FileAttributes.Normal, (int)dwFlags, 0)); }
/// <summary> /// Connects to the FTP server /// </summary> public override void Connect() { // Init wininet and get the base handle m_hInternet = WinInet.InternetOpen( null, // The 'user-agent' making the request INTERNET_OPEN.TYPE_PRECONFIG, // Use the default proxy settings null, // proxy name (no proxy) null, // proxy bypass (no bypass) 0 // Flags for the connection ); // Validate the connection and throw an exception if necessary ValidateConnection(m_hInternet); // Get a FTP handle to use to put files m_hFtp = WinInet.InternetConnect( m_hInternet, // The internet connection to use m_ftpAddress, m_ftpPort, // The FTP port number m_userName, m_passWord, INTERNET_SERVICE.FTP, // Open the connection for this type of service FtpConnectionFlags, // FTP Flags 0 // Application Context ); // Validate the handle and throw an exception if necessary ValidateConnection(m_hFtp); //save the home dir HomeDir = WinInet.GetFtpCurrentDirectory(m_hFtp); // Set the current directory to the path. If the path is empty, don't set // the current directory as this is invalid. if (m_path != "") { if (!m_path.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { string homeDir = HomeDir; if (!homeDir.EndsWith("/", StringComparison.OrdinalIgnoreCase)) { homeDir = homeDir + "/"; } m_path = homeDir + m_path + "/"; } if (!m_path.EndsWith("/", StringComparison.OrdinalIgnoreCase)) { //Mindspring's FTP behaves strangely if the current //directory isn't set with a trailing "/" m_path += "/"; } if (!RawDirectoryExists(m_path)) { if (!(HomeDir != null && HomeDir.StartsWith(m_path, StringComparison.OrdinalIgnoreCase) && m_path != "" && m_path.EndsWith("/", StringComparison.OrdinalIgnoreCase))) { throw new NoSuchDirectoryException(m_path); } } // Some FTP servers don't let you cwd to /, but we // still need to use it as our m_path. // // ValidateFTPCommand(pushDirectory(m_path)); } else { //remember what the default working directory assigned by the server was. m_path = HomeDir; } }
/// <summary> /// Looks up the content type in browser cache /// </summary> /// <param name="url">The url for which to check content type</param> /// <returns>The content type</returns> private static UrlContentTypeInfo GetContentTypeFromBrowserCache(string url) { UrlContentTypeInfo contentType = null; // throw out the query string and other bits of the url, if we can if (UrlHelper.IsUrl(url)) { Uri uri = new Uri(url); // by using the absolute uri, we're more likely to hit the cache url = UrlHelper.SafeToAbsoluteUri(uri); } // Get the header for this URL out of the cache and see if we // can get the content type out of the header Internet_Cache_Entry_Info info; if (WinInet.GetUrlCacheEntryInfo(url, out info)) { // Get the header string for the info struct string header = Marshal.PtrToStringAnsi(info.lpHeaderInfo); // scan through the lines until we find the content type line if (header != null) { string contentTypeString = null; string contentLengthString = null; string contentEncodingString = null; string[] lines = header.Split('\n'); foreach (string line in lines) { if (line.IndexOf(":", StringComparison.OrdinalIgnoreCase) > -1) { string[] parts = line.Split(':'); if (parts[0].ToUpperInvariant() == "CONTENT-TYPE") { // be aware the character encoding can be appended to the end of this line // following a semicolon if (parts[0].IndexOf(";", StringComparison.OrdinalIgnoreCase) > -1) { string[] subParts = parts[0].Split(';'); contentTypeString = subParts[0].Trim(); contentEncodingString = subParts[1].Trim(); } else { contentTypeString = parts[1].Trim(); } } else if (parts[0].ToUpperInvariant() == "CONTENT-LENGTH") { contentLengthString = parts[1].Trim(); } if (contentTypeString != null && contentLengthString != null) { break; } } } contentType = new UrlContentTypeInfo(contentTypeString, contentEncodingString, url, int.Parse(contentLengthString, CultureInfo.InvariantCulture)); } } return(contentType); }