Exemplo n.º 1
0
        protected override bool WriteFolder(Folder folder, string targetPath, out string folderPath)
        {
            var folderFolderName = LongPath.ToValidFileName(folder.DisplayName);

            folderPath = LongPath.Combine(targetPath, folderFolderName);
            return(true);
        }
Exemplo n.º 2
0
        protected override bool WriteList(List list, string targetPath, out string listPath)
        {
            var listFileName  = LongPath.ToValidFileName(string.Format(Options.ListFileNameFormat, list.DisplayName));
            var listBlobsPath = LongPath.Combine(targetPath, LongPath.ToValidFileName(string.Format(Options.ListBlobsFolderNameFormat, list.DisplayName)));

            var lwr = new ListWithRows(list);

            foreach (var row in lwr.Rows)
            {
                foreach (var column in list.Columns)
                {
                    if (column.DataType == ColumnDataType.Blob)
                    {
                        row.Values[column.Name] = ExtractBlobFromRow(list, row, column, listBlobsPath);
                    }
                }
            }

            listPath = LongPath.Combine(targetPath, listFileName);
            using (var writer = new StreamWriter(listPath, false, Options.Encoding))
            {
                JsonUtilities.Serialize(writer, lwr, Options.SerializationOptions);
            }
            return(true);
        }
Exemplo n.º 3
0
        public static string Combine(string path1, string path2)
        {
#if DOTNET5_4
            return(Path.Combine(path1, path2));
#else
            return(LongPath.Combine(path1, path2));
#endif
        }
Exemplo n.º 4
0
        protected override bool WriteList(List list, string targetPath, out string listPath)
        {
            var listFileName  = LongPath.ToValidFileName(string.Format(Options.ListFileNameFormat, list.DisplayName));
            var listBlobsPath = LongPath.Combine(targetPath, LongPath.ToValidFileName(string.Format(Options.ListBlobsFolderNameFormat, list.DisplayName)));

            listPath = LongPath.Combine(targetPath, listFileName);
            using (var writer = new StreamWriter(listPath, false, Options.Encoding))
            {
                WriteHeader(writer, list);

                writer.Write("<tr>");
                var columns = list.Columns.OrderBy(c => c.SortOrder).ToArray();
                foreach (var column in columns)
                {
                    writer.Write("<td>" + HtmlEncode(column.DisplayName) + "</td>");
                }
                writer.Write("</tr>");

                var rows = list.LoadRows();
                foreach (var row in rows)
                {
                    writer.Write("<tr>");
                    foreach (var column in columns)
                    {
                        string value = null;
                        if (column.DataType == ColumnDataType.Blob)
                        {
                            var blobProperties = row.GetValue <Dictionary <string, object> >(column.Name, null);
                            if (blobProperties != null)
                            {
                                var fileName    = blobProperties.GetValue <string>("FileName", null);
                                var contentType = blobProperties.GetValue <string>("ContentType", null);

                                value = ExtractBlobFromRow(list, row, column, listBlobsPath);
                                if (value != null)
                                {
                                    var isImage = (column.Options & ColumnOptions.IsImage) == ColumnOptions.IsImage ||
                                                  contentType != null && contentType.StartsWith("image/");

                                    value = string.Format("<a href=\"{0}\">{1}</a>", value, isImage ? string.Format("<img src=\"{0}\" alt=\"{1}\" />", value, fileName) : fileName);
                                }
                            }
                        }
                        else
                        {
                            value = HtmlEncode(row.GetValue <string>(column.Name, null));
                        }
                        writer.Write(string.Format("<td>{0}</td>", value));
                    }
                    writer.Write("</tr>");
                }

                WriteFooter(writer);
            }
            return(true);
        }
Exemplo n.º 5
0
        protected override bool WriteFolder(Folder folder, string targetPath, out string folderPath)
        {
            var folderFolderName = LongPath.ToValidFileName(folder.DisplayName);
            var folderFileName   = LongPath.Combine(targetPath, string.Format(Options.FolderFileNameFormat, folder.DisplayName));

            using (var writer = new StreamWriter(folderFileName, false, Options.Encoding))
            {
                JsonUtilities.Serialize(writer, folder, Options.SerializationOptions);
            }

            folderPath = LongPath.Combine(targetPath, folderFolderName);
            return(true);
        }
Exemplo n.º 6
0
 private static void LoadConfigurations(string path)
 {
     if (string.IsNullOrEmpty(path))
     {
         path = LongPath.Combine(AssemblyExtensions.ApplicationDirectory, "WebServiceLibraries");
     }
     try
     {
         var allFiles = LongPathDirectory.EnumerateFiles(path, "*.config", System.IO.SearchOption.AllDirectories);
         foreach (var file in allFiles)
         {
             try
             {
                 var info    = WebServiceRegistrationInfo.LoadFromFile(file);
                 var gllName = LongPath.ChangeExtension(file, ".gll");
                 if (info.RegisteredVIs != null)
                 {
                     foreach (var item in info.RegisteredVIs)
                     {
                         if (item.Type == WebServiceType.HttpGetMethod)
                         {
                             var registeredExecutable = new RegisteredHttpGetVI(
                                 _connectionManager,
                                 _httpServer,
                                 gllName,
                                 item.VIComponentName,
                                 item.UrlPath);
                             _connectionManager.AddConnectionType(registeredExecutable);
                         }
                     }
                 }
             }
             catch (Exception e)
             {
                 Log.LogError(0, e, $"Failed to load configuration: {file}");
             }
         }
     }
     catch (Exception enumerateException)
     {
         Log.LogError(0, enumerateException, "Failed to enumerate configuration files");
     }
 }
Exemplo n.º 7
0
        /// <inheritdoc />
        protected override async Task <int> RunAsync(IEnumerable <string> extraArguments, ProjectAndHostCreator projectAndHostCreator)
        {
            if (!LongPath.IsPathRooted(ProjectPath))
            {
                ProjectPath = LongPath.GetFullPath(LongPath.Combine(Environment.CurrentDirectory, ProjectPath));
            }

            Project project = await projectAndHostCreator.OpenProjectAsync(ProjectPath);

            CommandLineInterfaceApplication.WriteLineVerbose($"Opened project at {ProjectPath}");

            Envoy componentEnvoy = await ResolveComponentToBuildAsync(project);

            if (componentEnvoy == null)
            {
                return(1);
            }

            bool buildSucceeded = await LoadAndBuildComponentEnvoyAsync(componentEnvoy);

            return(buildSucceeded ? 0 : 1);
        }
Exemplo n.º 8
0
        private string GetUniqueBlobFilePath(Blob blob, string blobsPath)
        {
            var i = 0;

            do
            {
                string path;
                if (i == 0)
                {
                    path = LongPath.Combine(blobsPath, blob.FileName);
                }
                else
                {
                    path = LongPath.Combine(blobsPath, string.Format("{0} ({1}){2}", blob.FileNameWithoutExtension, i, blob.FileExtension));
                }

                if (!LongPath.FileExists(path))
                {
                    return(path);
                }

                i++;
            }while (true);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Enumerates the files present in the storage location referenced by this object.
        /// </summary>
        /// <param name="cancellationToken">CancellationToken to cancel the method.</param>
        /// <returns>Enumerable list of TransferEntry objects found in the storage location referenced by this object.</returns>
        public IEnumerable <TransferEntry> EnumerateLocation(CancellationToken cancellationToken)
        {
            Utils.CheckCancellation(cancellationToken);

            string filePattern = string.IsNullOrEmpty(this.SearchPattern) ? DefaultFilePattern : this.SearchPattern;

            SearchOption         searchOption        = this.Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
            IEnumerable <string> directoryEnumerator = null;
            ErrorEntry           errorEntry          = null;

            Utils.CheckCancellation(cancellationToken);

#if DOTNET5_4
            string fullPath = null;
            if (Interop.CrossPlatformHelpers.IsWindows)
            {
                fullPath = LongPath.ToUncPath(this.location.DirectoryPath);
            }
            else
            {
                fullPath = Path.GetFullPath(this.location.DirectoryPath);
            }
#else
            string fullPath = LongPath.ToUncPath(this.location.DirectoryPath);
#endif
            fullPath = AppendDirectorySeparator(fullPath);

            try
            {
                // Directory.GetFiles/EnumerateFiles will be broken when encounted special items, such as
                // files in recycle bins or the folder "System Volume Information". Rewrite this function
                // because our listing should not be stopped by these unexpected files.
                directoryEnumerator = EnumerateDirectoryHelper.EnumerateFiles(
                    fullPath,
                    filePattern,
                    this.listContinuationToken == null ? null : this.listContinuationToken.FilePath,
                    searchOption,
                    cancellationToken);
            }
            catch (Exception ex)
            {
                string errorMessage = string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.FailedToEnumerateDirectory,
                    this.location.DirectoryPath,
                    filePattern);

                TransferException exception =
                    new TransferException(TransferErrorCode.FailToEnumerateDirectory, errorMessage, ex);
                errorEntry = new ErrorEntry(exception);
            }

            if (null != errorEntry)
            {
                // We any exception we might get from Directory.GetFiles/
                // Directory.EnumerateFiles. Just return an error entry
                // to indicate error occured in this case.
                yield return(errorEntry);
            }

            if (null != directoryEnumerator)
            {
                foreach (string entry in directoryEnumerator)
                {
                    Utils.CheckCancellation(cancellationToken);

                    string relativePath = entry;

                    if (relativePath.StartsWith(fullPath, StringComparison.OrdinalIgnoreCase))
                    {
                        relativePath = relativePath.Remove(0, fullPath.Length);
                    }

                    var continuationToken = new FileListContinuationToken(relativePath);
                    if (relativePath.Length > Constants.MaxRelativePathLength)
                    {
                        relativePath = relativePath.Substring(0, Constants.MaxRelativePathLength / 2) + "..." + relativePath.Substring(relativePath.Length - Constants.MaxRelativePathLength / 2);
                    }

                    yield return(new FileEntry(
                                     relativePath,
                                     LongPath.Combine(this.location.DirectoryPath, relativePath),
                                     continuationToken));
                }
            }
        }
Exemplo n.º 10
0
        public static IEnumerable <string> EnumerateFiles(
            string path,
            string searchPattern,
            string fromFilePath,
            SearchOption searchOption,
            bool followsymlink,
            CancellationToken cancellationToken)
        {
            Utils.CheckCancellation(cancellationToken);

            if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
            {
                throw new ArgumentOutOfRangeException("searchOption");
            }

            // Remove whitespaces in the end.
            searchPattern = searchPattern.TrimEnd();
            if (searchPattern.Length == 0)
            {
                // Returns an empty string collection.
                return(new List <string>());
            }

            // To support patterns like "folderA\" aiming at listing files under some folder.
            if ("." == searchPattern)
            {
                searchPattern = "*";
            }

            Utils.CheckCancellation(cancellationToken);

            CheckSearchPattern(searchPattern);

            Utils.CheckCancellation(cancellationToken);

            // Check path permissions.
            string fullPath = null;

            if (Interop.CrossPlatformHelpers.IsWindows)
            {
                fullPath = LongPath.ToUncPath(path);
            }
            else
            {
                fullPath = Path.GetFullPath(path);
            }
#if CODE_ACCESS_SECURITY
            CheckPathDiscoveryPermission(fullPath);
#endif // CODE_ACCESS_SECURITY

            string patternDirectory = LongPath.GetDirectoryName(searchPattern);
#if CODE_ACCESS_SECURITY
            if (!string.IsNullOrEmpty(patternDirectory))
            {
                CheckPathDiscoveryPermission(LongPath.Combine(fullPath, patternDirectory));
            }
#endif // CODE_ACCESS_SECURITY

            if (!string.IsNullOrEmpty(fromFilePath) &&
                !string.IsNullOrEmpty(patternDirectory))
            {
                // if file pattern is like folder\fileName*, we'll list location\folder with pattern fileName*
                // but the listted relative path will still be like folder\fileName1, and the continuation token will look the same.
                // Then here we need to make continuation token to be path relative to location\folder.
                string tmpPatternDir = AppendDirectorySeparator(patternDirectory);
                fromFilePath = fromFilePath.Substring(tmpPatternDir.Length);
            }

            string fullPathWithPattern = LongPath.Combine(fullPath, searchPattern);

            // To support patterns like "folderA\" aiming at listing files under some folder.
            char lastC = fullPathWithPattern[fullPathWithPattern.Length - 1];
            if (Path.DirectorySeparatorChar == lastC ||
                Path.AltDirectorySeparatorChar == lastC ||
                Path.VolumeSeparatorChar == lastC)
            {
                fullPathWithPattern = fullPathWithPattern + '*';
            }

            string directoryName = AppendDirectorySeparator(LongPath.GetDirectoryName(fullPathWithPattern));
            string filePattern   = fullPathWithPattern.Substring(directoryName.Length);

            if (!LongPathDirectory.Exists(directoryName))
            {
                throw new DirectoryNotFoundException(
                          string.Format(
                              CultureInfo.CurrentCulture,
                              Resources.PathNotFound,
                              directoryName));
            }

            Utils.CheckCancellation(cancellationToken);
            return(InternalEnumerateFiles(directoryName, filePattern, fromFilePath, searchOption, followsymlink, cancellationToken));
        }
Exemplo n.º 11
0
        private static IEnumerable <string> InternalEnumerateFiles(
            string directoryName,
            string filePattern,
            string fromFilePath,
            SearchOption searchOption,
            bool followsymlink,
            CancellationToken cancellationToken)
        {
            Stack <string> folders = new Stack <string>();
            Stack <string> currentFolderSubFolders = new Stack <string>();

            folders.Push(directoryName);

            string[] pathSegList             = null;
            bool     passedContinuationToken = false;
            int      pathSegListIndex        = 0;

            if (null != fromFilePath)
            {
                pathSegList = fromFilePath.Split(new char[] { Path.DirectorySeparatorChar });
            }
            else
            {
                passedContinuationToken = true;
            }

            while (folders.Count > 0)
            {
                string folder = AppendDirectorySeparator(folders.Pop());

                Utils.CheckCancellation(cancellationToken);

                // Skip non-existent folders
                if (!LongPathDirectory.Exists(folder))
                {
#if DOTNET5_4
                    if (CrossPlatformHelpers.IsLinux)
                    {
                        if (!SymlinkedDirExists(folder))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }
#else
                    continue;
#endif
                }

#if CODE_ACCESS_SECURITY // Only accessible to fully trusted code in non-CAS models
                try
                {
                    CheckPathDiscoveryPermission(folder);
                }
                catch (SecurityException)
                {
                    // Ignore this folder if we have no right to discovery it.
                    continue;
                }
                catch (UnauthorizedAccessException)
                {
                    // Ignore this folder if we have no right to discovery it.
                    continue;
                }
#else // CODE_ACCESS_SECURITY
                try
                {
                    // In non-CAS scenarios, it's still important to check for folder accessibility
                    // since the OS can block access to some paths. Getting files from a location
                    // will force path discovery checks which will indicate whether or not the user
                    // is authorized to access the directory.
                    foreach (var fileItem in LongPathDirectory.EnumerateFileSystemEntries(folder, "*", SearchOption.TopDirectoryOnly))
                    {
                        // Just try to get the first item in directly to check whether has permission to access the directory.
                        break;
                    }
                }
                catch (SecurityException)
                {
                    // Ignore this folder if we have no right to discovery it.
                    continue;
                }
                catch (UnauthorizedAccessException)
                {
                    // Ignore this folder if we have no right to discovery it.
                    continue;
                }
                catch (Exception ex)
                {
                    throw new TransferException(string.Format(CultureInfo.CurrentCulture, Resources.EnumerateDirectoryException, folder), ex);
                }
#endif // CODE_ACCESS_SECURITY

                // Return all files contained directly in this folder (which occur after the continuationTokenFile)
                // Only consider the folder if the continuation token is already past or the continuation token may be passed by
                // a file within this directory (based on pathSegListIndex and the patSegList.Length)
                if (passedContinuationToken ||
                    (pathSegList.Length - 1 == pathSegListIndex))
                {
                    string continuationTokenFile = null;

                    if (!passedContinuationToken)
                    {
                        continuationTokenFile = pathSegList[pathSegListIndex];
                    }

                    // Load files directly under this folder.
                    foreach (var filePath in Utils.CatchException(() =>
                    {
                        return(LongPathDirectory.EnumerateFileSystemEntries(folder, filePattern, SearchOption.TopDirectoryOnly));
                    },
                                                                  (ex) =>
                    {
                        throw new TransferException(string.Format(CultureInfo.CurrentCulture, Resources.EnumerateDirectoryException, folder), ex);
                    }))
                    {
                        Utils.CheckCancellation(cancellationToken);

                        EnumerateFileEntryInfo fileEntryInfo = null;

                        try
                        {
#if DOTNET5_4
                            if (CrossPlatformHelpers.IsLinux)
                            {
                                fileEntryInfo = GetFileEntryInfo(filePath);
                            }
                            else
                            {
                                fileEntryInfo = new EnumerateFileEntryInfo()
                                {
                                    FileName       = LongPath.GetFileName(filePath),
                                    FileAttributes = LongPathFile.GetAttributes(filePath)
                                };
                            }
#else
                            fileEntryInfo = new EnumerateFileEntryInfo()
                            {
                                FileName       = LongPath.GetFileName(filePath),
                                FileAttributes = LongPathFile.GetAttributes(filePath)
                            };
#endif
                        }
                        // Cross-plat file system accessibility settings may cause exceptions while
                        // retrieving attributes from inaccessible paths. These paths shold be skipped.
                        catch (FileNotFoundException) { }
                        catch (IOException) { }
                        catch (UnauthorizedAccessException) { }
                        catch (Exception ex)
                        {
                            throw new TransferException(string.Format(CultureInfo.CurrentCulture, Resources.FailedToGetFileInfoException, filePath), ex);
                        }

                        if (null == fileEntryInfo)
                        {
                            continue;
                        }

                        if (FileAttributes.Directory != (fileEntryInfo.FileAttributes & FileAttributes.Directory))
                        {
                            if (passedContinuationToken)
                            {
                                yield return(LongPath.Combine(folder, fileEntryInfo.FileName));
                            }
                            else
                            {
                                if (CrossPlatformHelpers.IsLinux)
                                {
                                    if (!passedContinuationToken)
                                    {
                                        if (string.Equals(fileEntryInfo.FileName, continuationTokenFile, StringComparison.Ordinal))
                                        {
                                            passedContinuationToken = true;
                                        }
                                    }
                                    else
                                    {
                                        yield return(LongPath.Combine(folder, fileEntryInfo.FileName));
                                    }
                                }
                                else
                                {
                                    // Windows file system is case-insensitive; OSX and Linux are case-sensitive
                                    var comparison    = CrossPlatformHelpers.IsWindows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
                                    int compareResult = string.Compare(fileEntryInfo.FileName, continuationTokenFile, comparison);
                                    if (compareResult < 0)
                                    {
                                        // Skip files prior to the continuation token file
                                        continue;
                                    }

                                    passedContinuationToken = true;

                                    if (compareResult > 0)
                                    {
                                        yield return(LongPath.Combine(folder, fileEntryInfo.FileName));
                                    }
                                }
                            }
                        }
                    }

                    // Passed folder which continuation token file is under,
                    // set passedContinuationToken to true.
                    passedContinuationToken = true;
                }

                // Next add sub-folders for processing
                if (SearchOption.AllDirectories == searchOption)
                {
                    string fromSubfolder  = null;
                    bool   passedSubfoler = passedContinuationToken;
                    if (!passedContinuationToken)
                    {
                        fromSubfolder = pathSegList[pathSegListIndex];
                        pathSegListIndex++;
                    }

                    // Add sub-folders.
                    foreach (var filePath in Utils.CatchException(() =>
                    {
                        return(LongPathDirectory.EnumerateFileSystemEntries(folder, "*", SearchOption.TopDirectoryOnly));
                    },
                                                                  (ex) =>
                    {
                        throw new TransferException(string.Format(CultureInfo.CurrentCulture, Resources.EnumerateDirectoryException, folder), ex);
                    }))
                    {
                        Utils.CheckCancellation(cancellationToken);

                        EnumerateFileEntryInfo fileEntryInfo = null;

                        try
                        {
                            if (CrossPlatformHelpers.IsLinux)
                            {
                                fileEntryInfo = GetFileEntryInfo(filePath);
                            }
                            else
                            {
                                fileEntryInfo = new EnumerateFileEntryInfo()
                                {
                                    FileName       = LongPath.GetFileName(filePath),
                                    FileAttributes = LongPathFile.GetAttributes(filePath)
                                };
                            }
                        }
                        // Cross-plat file system accessibility settings may cause exceptions while
                        // retrieving attributes from inaccessible paths. These paths shold be skipped.
                        catch (FileNotFoundException) { }
                        catch (IOException) { }
                        catch (UnauthorizedAccessException) { }
                        catch (Exception ex)
                        {
                            throw new TransferException(string.Format(CultureInfo.CurrentCulture, Resources.FailedToGetFileInfoException, filePath), ex);
                        }

                        if (null == fileEntryInfo)
                        {
                            continue;
                        }

                        if (FileAttributes.Directory == (fileEntryInfo.FileAttributes & FileAttributes.Directory) &&
                            !fileEntryInfo.FileName.Equals(@".") &&
                            !fileEntryInfo.FileName.Equals(@".."))
                        {
                            bool toBeEnumerated = false;
                            if (CrossPlatformHelpers.IsLinux)
                            {
                                toBeEnumerated = ToEnumerateTheSubDir(LongPath.Combine(folder, fileEntryInfo.FileName), fileEntryInfo, followsymlink);
                            }
                            // TODO: Ignore junction point or not. Make it configurable.
                            else if (FileAttributes.ReparsePoint != (fileEntryInfo.FileAttributes & FileAttributes.ReparsePoint))
                            {
                                toBeEnumerated = true;
                            }

                            if (toBeEnumerated)
                            {
                                if (passedSubfoler)
                                {
                                    currentFolderSubFolders.Push(LongPath.Combine(folder, fileEntryInfo.FileName));
                                }
                                else
                                {
                                    if (CrossPlatformHelpers.IsLinux)
                                    {
                                        if (string.Equals(fileEntryInfo.FileName, fromSubfolder, StringComparison.Ordinal))
                                        {
                                            passedSubfoler = true;
                                            currentFolderSubFolders.Push(LongPath.Combine(folder, fileEntryInfo.FileName));
                                        }
                                    }
                                    else
                                    {
                                        // Windows file system is case-insensitive; OSX and Linux are case-sensitive
                                        var comparison    = CrossPlatformHelpers.IsWindows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
                                        int compareResult = string.Compare(fileEntryInfo.FileName, fromSubfolder, comparison);

                                        if (compareResult >= 0)
                                        {
                                            passedSubfoler = true;
                                            currentFolderSubFolders.Push(LongPath.Combine(folder, fileEntryInfo.FileName));

                                            if (compareResult > 0)
                                            {
                                                passedContinuationToken = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (currentFolderSubFolders.Count <= 0)
                    {
                        passedContinuationToken = true;
                    }
                    else
                    {
                        while (currentFolderSubFolders.Count > 0)
                        {
                            folders.Push(currentFolderSubFolders.Pop());
                        }
                    }
                }
            }
        }
Exemplo n.º 12
0
        protected override bool WriteList(List list, string targetPath, out string listPath)
        {
            var listFileName  = LongPath.ToValidFileName(string.Format(Options.ListFileNameFormat, list.DisplayName));
            var listBlobsPath = LongPath.Combine(targetPath, LongPath.ToValidFileName(string.Format(Options.ListBlobsFolderNameFormat, list.DisplayName)));

            listPath = LongPath.Combine(targetPath, listFileName);
            using (var writer = new StreamWriter(listPath, false, Options.Encoding))
            {
                var columns = list.Columns.OrderBy(c => c.SortOrder).ToArray();
                var sep     = false;
                foreach (var column in columns)
                {
                    if (sep)
                    {
                        writer.Write(Options.Separator);
                    }
                    else
                    {
                        sep = true;
                    }
                    writer.Write(CsvEncode(column.DisplayName));
                }
                writer.WriteLine();

                var rows = list.LoadRows();
                foreach (var row in rows)
                {
                    sep = false;
                    foreach (var column in columns)
                    {
                        if (sep)
                        {
                            writer.Write(Options.Separator);
                        }
                        else
                        {
                            sep = true;
                        }

                        object value = null;
                        if (column.DataType == ColumnDataType.Blob)
                        {
                            if (list.Parent != null && list.Parent.Server != null)
                            {
                                // we can download the blob
                                value = ExtractBlobFromRow(list, row, column, listBlobsPath);
                            }
                        }
                        else
                        {
                            value = row.GetValue(column.Name);
                        }

                        if (value != null)
                        {
                            writer.Write(value);
                        }
                    }
                    writer.WriteLine();
                }
            }
            return(true);
        }