Ejemplo n.º 1
0
        internal async Task DownloadFile(WsFile sourceFile, Stream targetStream, CancellationToken cancellationToken, IProgress <int> progress)
        {
            if (sourceFile == null)
            {
                throw new ArgumentNullException(nameof(sourceFile));
            }
            if (targetStream == null)
            {
                throw new ArgumentNullException(nameof(targetStream));
            }
            if (targetStream.CanWrite == false)
            {
                throw new NotSupportedException("The target stream does not support writing.");
            }
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }

            progress?.Report(0);

            using (HttpResponseMessage response = await DownloadFile(sourceFile, cancellationToken))
            {
                long fileSize = response.Content.Headers.ContentLength ?? sourceFile.Size;
                using (TransportStream sourceTrasportStream = new TransportStream(await response.Content.ReadAsStreamAsync(), fileSize, progress))
                {
                    await sourceTrasportStream.CopyToAsync(targetStream, CalculateBuffer(fileSize), cancellationToken);

                    progress?.Report(100);
                }
            }
        }
Ejemplo n.º 2
0
        public void WsFile_ReadFromServer2()
        {
            IrbisConnection connection = Connection
                                         .ThrowIfNull("Connection");
            IrbisProvider provider = new ConnectedClient(connection);

            FileSpecification specification = new FileSpecification
                                              (
                IrbisPath.MasterFile,
                "IBIS",
                "PAZK42.WS"
                                              );
            WsFile wss = WsFile.ReadFromServer
                         (
                provider,
                specification
                         );

            if (!ReferenceEquals(wss, null))
            {
                string[] lines = wss.Pages
                                 .Select
                                 (
                    item => item.Name
                                 )
                                 .ToArray();
                string text = string.Join("|", lines);
                Write(text);
            }
        }
Ejemplo n.º 3
0
        public Form2()
        {
            InitializeComponent();

            Grid = new SiberianFieldGrid
            {
                Dock = DockStyle.Fill
            };
            Controls.Add(Grid);

            Record = PlainText.ReadOneRecord
                     (
                "record.txt",
                IrbisEncoding.Utf8
                     )
                     .ThrowIfNull("Record");
            Worksheet = WsFile.ReadLocalFile
                        (
                "PAZK31.WS",
                IrbisEncoding.Ansi
                        );

            WorksheetPage page = Worksheet.Pages[1];

            Grid.Load
            (
                page,
                Record
            );
        }
        public async Task <FileSystemExitCode> UploadFile(FileInfo sourceFileName, WsPath targetFileName, bool overwrite, IProgress <int> progress, CancellationToken cancellationToken)
        {
            try
            {
                await EnsureLogin();

                bool       uploadDirect   = overwrite;
                WsFilePath targetFilePath = targetFileName.GetFilePath();
                if (overwrite == false)
                {
                    WsFile file = await _apiClient.FindFile(targetFilePath);

                    if (file != null)
                    {
                        if (overwrite == false)
                        {
                            return(FileSystemExitCode.FileExists);
                        }
                        using (FileStream sourceStream = sourceFileName.OpenRead())
                        {
                            await file.Replace(sourceStream, cancellationToken, progress);
                        }
                    }
                    else
                    {
                        uploadDirect = true;
                    }
                }
                if (uploadDirect)
                {
                    using (FileStream sourceStream = sourceFileName.OpenRead())
                    {
                        await _apiClient.UploadFile(sourceStream, sourceStream.Length, targetFilePath, cancellationToken, progress);
                    }
                }
                return(FileSystemExitCode.OK);
            }
            catch (TaskCanceledException)
            {
                return(FileSystemExitCode.UserAbort);
            }
            catch (FileNotFoundException)
            {
                return(FileSystemExitCode.FileNotFound);
            }
            // TODO: dialog for file password, Exception throw in WsApiClient.CheckResultStatus
            //catch (??)
            //{
            //    return ??;
            //}
            catch (Exception ex)
            {
                if (ShowError("Upload file error", ex, true) == false)
                {
                    return(FileSystemExitCode.UserAbort);
                }
                return(FileSystemExitCode.ReadError);
            }
        }
Ejemplo n.º 5
0
 public void Rename(WsFile file, string newName)
 {
     if (_dic.TryGetValue(file.Ident, out WsFile newFile))
     {
         newFile.ChangeNameInInstance(newName);
         Log($"Rename file to {newName}", file.PathInfo);
     }
 }
Ejemplo n.º 6
0
        public async Task <WsFile> GetFile(WsFilePath filePath)
        {
            WsFile file = await FindFile(filePath);

            if (file == null)
            {
                throw new FileNotFoundException("Required file not found on server.", filePath.ToString());
            }
            return(file);
        }
Ejemplo n.º 7
0
        private static void UpdateDocRemoveStatus(WsFile wsFile)
        {
            //For Server 2
            using (var db = new S2DbContext())
            {
                SqlParameter p1 = new SqlParameter("@DocumentNumber", wsFile.Number);

                try
                {
                    db.Database.ExecuteSqlCommand("EXEC [S2CLR].spUpdateDRMSRemoveStatus @DocumentNumber", p1);
                }
                catch (SqlException ex)
                {
                    ex = null;
                }
            }

            //For SSC
            using (var db = new SSCDbContext())
            {
                SqlParameter p1 = new SqlParameter("@DocNumber", wsFile.Number);
                SqlParameter p2 = new SqlParameter("@IsRET", wsFile.WsFileType == WsFileType.Ret);
                SqlParameter p3 = new SqlParameter("@UserId", AmUtil.GetCurrentUser);

                try
                {
                    db.Database.ExecuteSqlCommand("EXEC spRemoveDRMSDocument @DocNumber, @IsRET, @UserId", p1, p2, p3);
                }
                catch (SqlException ex)
                {
                    ex = null;
                }
            }

            //if (wsFile.IsServer2)
            //{
            //    using (var db = new S2DbContext())
            //    {
            //        SqlParameter p1 = new SqlParameter("@DocumentNumber", wsFile.Number);

            //        db.Database.ExecuteSqlCommand("EXEC [S2CLR].spUpdateDRMSRemoveStatus @DocumentNumber", p1);
            //    }
            //}
            //else
            //{
            //    using (var db = new SSCDbContext())
            //    {
            //        SqlParameter p1 = new SqlParameter("@DocNumber", wsFile.Number);
            //        SqlParameter p2 = new SqlParameter("@IsRET", wsFile.WsFileType == WsFileType.Ret);
            //        SqlParameter p3 = new SqlParameter("@UserId", AmUtil.GetCurrentUser);

            //        db.Database.ExecuteSqlCommand("EXEC spRemoveDRMSDocument @DocNumber, @IsRET, @UserId", p1, p2, p3);
            //    }
            //}
        }
Ejemplo n.º 8
0
        internal async Task <WsFile> UploadFile(Stream sourceStream, long sourceSize, WsFilePath targetFilePath, bool ensureDeleteIfNeed, CancellationToken cancellationToken, IProgress <int> progress)
        {
            if (sourceStream == null)
            {
                throw new ArgumentNullException(nameof(sourceStream));
            }
            if (sourceStream.CanRead == false)
            {
                throw new NotSupportedException("The source stream does not support reading.");
            }
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            CheckConnected();
            progress?.Report(0);

            if (ensureDeleteIfNeed)
            {
                WsFile file = await FindFile(targetFilePath);

                if (file != null)
                {
                    await file.Delete();
                }
            }

            MultipartFormDataContent form = new MultipartFormDataContent();

            form.Add(new StringContent(WebUtility.UrlEncode(targetFilePath.Name)), "name");
            form.Add(new StringContent(_loginInfo.LoginToken), "wst");
            form.Add(new StringContent(WebUtility.UrlEncode(targetFilePath.Folder.FullPath)), "folder");
            form.Add(new StringContent(targetFilePath.IsPrivate ? "1" : "0"), "private");
            form.Add(new StringContent("0"), "adult");
            form.Add(new StringContent(sourceSize.ToString()), "total");
            //form.Add(new StringContent(""), "offset");

            TransportStream        sourceTransportStream = new TransportStream(sourceStream, sourceSize, progress);
            TransportStreamContent fileContent           = new TransportStreamContent(sourceTransportStream, targetFilePath.Name, CalculateBuffer(sourceSize));

            form.Add(fileContent);

            UploadResult uploadResult = await _httpClient.PostFormData <UploadResult>(await GetUploadFileUrl(), form, cancellationToken, false, TimeSpan.FromHours(24));

            if (string.IsNullOrWhiteSpace(uploadResult?.Ident))
            {
                throw new IOException($"Server upload error: result={uploadResult.Result}");
            }

            return(_createdFileResolver.Add(targetFilePath.Folder, targetFilePath.Name, uploadResult.Ident, sourceSize));
        }
Ejemplo n.º 9
0
 public WsFile Add(string fileName, string fileIdent, long fileSize, bool isPrivate)
 {
     return(_dic.GetOrAdd(fileIdent, x =>
     {
         if (_resolverTask == null || _resolverTask.IsCompleted || _resolverTask.IsCanceled || _resolverTask.IsFaulted)
         {
             _cancellationTokenSource = new CancellationTokenSource();
             _resolverTask = ContinuosResolve(_cancellationTokenSource.Token);
         }
         WsFile newFile = new WsFile(_folderPath, fileName, fileIdent, fileSize, _apiClient);
         Log("Add file", newFile.PathInfo);
         return newFile;
     }));
 }
Ejemplo n.º 10
0
 public bool RemoveFileAndFolderIfEmpty(WsFile foundedFile)
 {
     if (_dic.TryRemove(foundedFile.Ident, out WsFile removedFile))
     {
         Log("Remove file", foundedFile.PathInfo);
         foundedFile.ChangeStateToReady();
         removedFile.ChangeStateToReady();
         if (_dic.Count == 0)
         {
             _removeFromParent(_folderPath);
             return(true);
         }
     }
     return(false);
 }
 public IEnumerable <WsItem> GetItems()
 {
     if (_disposed)
     {
         throw new InvalidOperationException($"Enumerate in {nameof(WsItemsReaderEngine)} is disposed");
     }
     if (_getItemsInvoked)
     {
         throw new InvalidOperationException($"Enumerate in {nameof(WsItemsReaderEngine)} can call only ones");
     }
     _getItemsInvoked = true;
     CreatedFileResolver.IFolderItemsResolver folderItemsResolver = _useCreatedFileResolver ? _apiClient._createdFileResolver.FindFolderItemsResolver(_folderPath) : null;
     while (AppVersion == 0 && _disposed == false)
     {
         if (_xmlReader.Name == "folder")
         {
             yield return(CreateItemInfo <WsFolder>());
         }
         else if (_xmlReader.Name == "file")
         {
             WsFile file = CreateItemInfo <WsFile>();
             if (file.IsReady)
             {
                 if (folderItemsResolver?.RemoveFileAndFolderIfEmpty(file) == true)
                 {
                     folderItemsResolver = null;
                 }
                 yield return(file);
             }
         }
         else if (_xmlReader.Name == "app_version")
         {
             AppVersion = _xmlReader.ReadElementContentAsInt();
         }
         else
         {
             break;
         }
     }
     Dispose();
     if (folderItemsResolver != null)
     {
         foreach (WsFile file in folderItemsResolver.GetCreatedFilesInProgress())
         {
             yield return(file);
         }
     }
 }
Ejemplo n.º 12
0
        internal async Task MoveItem(WsItem sourceItem, WsFolder targetFolder)
        {
            if (sourceItem == null)
            {
                throw new ArgumentNullException(nameof(sourceItem));
            }
            if (targetFolder == null)
            {
                throw new ArgumentNullException(nameof(targetFolder));
            }
            if (sourceItem.PathInfoGeneric.Folder.Equals(targetFolder.PathInfo))
            {
                throw new ArgumentException($"{nameof(sourceItem)} and {nameof(targetFolder)} are equal folder.");
            }
            CheckConnected();

            Task <Result> MoveFunc()
            {
                FormUrlEncodedContent formContent = CreateFormContent(new[]
                {
                    new KeyValuePair <string, string>("src", sourceItem.PathInfoGeneric.FullPath),
                    new KeyValuePair <string, string>("src_private", sourceItem.PathInfoGeneric.IsPrivate ? "1" : "0"),
                    new KeyValuePair <string, string>("dest", targetFolder.PathInfo.FullPath),
                    new KeyValuePair <string, string>("dest_private", targetFolder.PathInfo.IsPrivate ? "1" : "0"),
                });

                return(_httpClient.PostFormData <Result>(API_MOVE_FILE_URI, formContent));
            }

            if (sourceItem is WsFile file)
            {
                WsFile targetFile = await FindFile(new WsFilePath(targetFolder.PathInfo, file.PathInfo.Name));

                if (targetFile != null)
                {
                    await targetFile.Delete();
                }
                await PostFormDataWithNotFoundAndLoginRetry(file, MoveFunc);
            }
            else
            {
                await PostFormDataWithLoginRetry(MoveFunc);
            }

            _createdFileResolver.MoveItem(sourceItem, targetFolder);
            sourceItem.ChangePathInInstance(targetFolder.PathInfo.FullPath + sourceItem.PathInfoGeneric.Name, targetFolder.PathInfo.IsPrivate);
        }
Ejemplo n.º 13
0
        public FileSystemExitCode CopyFile(WsPath sourceFilePath, WsPath targetPath, bool overwrite, IProgress <int> progress)
        {
            try
            {
                using (ThreadKeeper exec = new ThreadKeeper())
                {
                    return(exec.ExecAsync(async(cancellationToken) =>
                    {
                        await EnsureLogin();
                        WsFile sourceFile = await _apiClient.FindFile(sourceFilePath.GetFilePath());
                        if (sourceFile != null)
                        {
                            if (overwrite == false)
                            {
                                if (await _apiClient.FindFile(targetPath.GetFilePath()) != null)
                                {
                                    return FileSystemExitCode.FileExists;
                                }
                            }
                        }

                        if (sourceFile == null)
                        {
                            return FileSystemExitCode.FileNotFound;
                        }
                        WsFolder targetFolder = await _apiClient.FindFolder(targetPath.Parent.GetFolderPath());
                        if (targetFolder == null)
                        {
                            return FileSystemExitCode.FileNotFound;
                        }

                        await sourceFile.Copy(targetFolder, cancellationToken, new ThreadKeeperCancellableProgress(exec, progress));
                        return FileSystemExitCode.OK;
                    }));
                }
            }
            catch (TaskCanceledException)
            {
                return(FileSystemExitCode.UserAbort);
            }
            catch (Exception ex)
            {
                ShowError("Copy file error", ex, false);
                return(FileSystemExitCode.WriteError);
            }
        }
Ejemplo n.º 14
0
        private async Task <HttpResponseMessage> DownloadFile(WsFile file, CancellationToken cancellationToken)
        {
            FileLinkResult fileLinkResult = await PostFormDataWithNotFoundAndLoginRetry(file, () =>
            {
                FormUrlEncodedContent formContent = CreateFormContent(new[]
                {
                    new KeyValuePair <string, string>("ident", file.Ident),
                    new KeyValuePair <string, string>("password", ""),
                    new KeyValuePair <string, string>("download_type", "file_download"),
                    new KeyValuePair <string, string>("device_uuid", _deviceUuid.ToString()),
                    new KeyValuePair <string, string>("device_res_x", "1920"),
                    new KeyValuePair <string, string>("device_res_x", "1080"),
                    new KeyValuePair <string, string>("force_https", "1")
                });
                return(_httpClient.PostFormData <FileLinkResult>(API_FILE_LINK_URI, formContent, cancellationToken));
            });

            return(await _httpClient.GetData(new Uri(fileLinkResult.Link), cancellationToken));
        }
Ejemplo n.º 15
0
 public PreviewBitmapResult GetPreviewBitmap(WsPath filePath, int width, int height)
 {
     try
     {
         return(ExecuteAsync(filePath, async() =>
         {
             WsFile file = await _apiClient.FindFile(filePath.GetFilePath());
             if (file != null)
             {
                 WsFolder folder = await _apiClient.FindFolder(filePath.Parent.GetFolderPath());
                 if (folder != null)
                 {
                     WsFilePreview filePreview = await _filesPreviewCache.FindFilePreview(folder, filePath.Name);
                     byte[] jpgData = await filePreview.JpgData;
                     if (jpgData?.Length > 0)
                     {
                         using (MemoryStream jpgStream = new MemoryStream(jpgData))
                         {
                             Image jpg = Image.FromStream(jpgStream);
                             decimal ratio = (decimal)jpg.Width / jpg.Height;
                             if (ratio > 1)
                             {
                                 height = (int)(height / ratio);
                             }
                             if (ratio < 1)
                             {
                                 width = (int)(width / ratio);
                             }
                             Bitmap bmp = new Bitmap(jpg, width, height);
                             return PreviewBitmapResult.Extracted(bmp, null, false);
                         }
                     }
                 }
             }
             return PreviewBitmapResult.None;
         }));
     }
     catch
     {
         return(PreviewBitmapResult.None);
     }
 }
Ejemplo n.º 16
0
        public static WsFile GetWsFile(IManDocument imDoc, string fldrPath = null)
        {
            var wsFile = new WsFile
            {
                Author       = WsUtility.GetWsUser(imDoc.Author),
                IsCheckedOut = imDoc.CheckedOut,
                Description  = imDoc.Description,
                Extn         = imDoc.Type.ApplicationExtension,

                IsLocked        = imDoc.Locked,
                Name            = imDoc.Name,
                FilePath        = fldrPath,
                Number          = imDoc.Number,
                ObjectID        = imDoc.ObjectID,
                Operator        = WsUtility.GetWsUser(imDoc.Operator),
                Size            = imDoc.Size,
                Version         = imDoc.Version,
                VersionCount    = imDoc.Versions.Count,
                IsLatestVersion = imDoc.IsLatestVersion,

                CreationDate = imDoc.CreationDate.ToString("G", CultureInfo.CreateSpecificCulture("en-us")),
            };

            wsFile = PopulateCustomAttr(wsFile, imDoc);

            if (wsFile.IsRecord)
            {
                foreach (IManDocumentHistory docHistory in imDoc.HistoryList)
                {
                    if (docHistory.Operation.Equals("Declared", StringComparison.OrdinalIgnoreCase))
                    {
                        wsFile.RecordDate = docHistory.Date;
                        wsFile.RecordUser = docHistory.User;
                    }
                }
            }

            wsFile.IsUnderPreservation = wsFile.Status.Equals("UNDER PRESERVATION", StringComparison.OrdinalIgnoreCase);

            return(wsFile);
        }
Ejemplo n.º 17
0
 public bool DeleteFile(WsPath filePath)
 {
     try
     {
         return(ExecuteAsync(filePath, async() =>
         {
             WsFile file = await _apiClient.FindFile(filePath.GetFilePath());
             if (file == null)
             {
                 return false;
             }
             await file.Delete();
             return true;
         }));
     }
     catch (Exception ex)
     {
         ShowError("Delete file error", ex, false);
         return(false);
     }
 }
Ejemplo n.º 18
0
        public async Task <FileSystemExitCode> DownloadFile(WsPath sourceFileName, FileInfo targetFileName, bool overwrite, IProgress <int> progress, bool deleteAfter, CancellationToken cancellationToken)
        {
            try
            {
                await EnsureLogin();

                WsFile file = await _apiClient.GetFile(sourceFileName.GetFilePath());

                FileMode mode = overwrite ? FileMode.Create : FileMode.CreateNew;

                using (FileStream targetStream = targetFileName.Open(mode, FileAccess.Write))
                {
                    await file.Download(targetStream, cancellationToken, progress);
                }
                targetFileName.CreationTime = targetFileName.LastWriteTime = file.Created;
                if (deleteAfter)
                {
                    await file.Delete();
                }
                return(FileSystemExitCode.OK);
            }
            catch (TaskCanceledException)
            {
                targetFileName.Delete();
                return(FileSystemExitCode.UserAbort);
            }
            catch (FileNotFoundException)
            {
                return(FileSystemExitCode.FileNotFound);
            }
            catch (Exception ex)
            {
                targetFileName.Delete();
                if (ShowError("Download file error", ex, true) == false)
                {
                    return(FileSystemExitCode.UserAbort);
                }
                return(FileSystemExitCode.ReadError);
            }
        }
Ejemplo n.º 19
0
        private async Task <TResult> PostFormDataWithNotFoundAndLoginRetry <TResult>(WsFile file, Func <Task <TResult> > postFunc) where TResult : Result
        {
            TResult result;

            if (file.IsReady == false)
            {
                try
                {
                    result = await PostFormDataWithLoginRetry(postFunc);
                }
                catch (FileNotFoundException)
                {
                    await file.WaitForReadyFile();

                    result = await PostFormDataWithLoginRetry(postFunc);
                }
            }
            else
            {
                result = await PostFormDataWithLoginRetry(postFunc);
            }
            return(result);
        }
Ejemplo n.º 20
0
        internal async Task RenameItem(WsItem item, string newName)
        {
            if (string.IsNullOrWhiteSpace(newName))
            {
                throw new ArgumentNullException(nameof(newName));
            }
            CheckConnected();

            Task <Result> RenameFunc()
            {
                FormUrlEncodedContent formContent = CreateFormContent(new[]
                {
                    new KeyValuePair <string, string>("ident", item.Ident),
                    new KeyValuePair <string, string>("name", newName)
                });

                return(_httpClient.PostFormData <Result>(API_RENAME_FILE_URI, formContent));
            }

            if (item is WsFile file)
            {
                WsFile targetFile = await FindFile(new WsFilePath(file.PathInfo.Folder, newName));

                if (targetFile != null)
                {
                    await targetFile.Delete();
                }
                await PostFormDataWithNotFoundAndLoginRetry(file, RenameFunc);
            }
            else
            {
                await PostFormDataWithLoginRetry(RenameFunc);
            }

            _createdFileResolver.RenameItem(item, newName);
            item.ChangeNameInInstance(newName);
        }
Ejemplo n.º 21
0
        static void Main(string[] args)
        {
            if (args.Length != 3)
            {
                Console.WriteLine
                (
                    "RecordDumper <connection-string> "
                    + "<search-expression> <output-file>"
                );

                return;
            }

            string connectionString = args[0];
            string searchExpression = args[1];
            string outputFileName   = args[2];

            try
            {
                JObject config
                    = JsonUtility.ReadObjectFromFile("dumperConfig.json");
                int   etalonTag   = config["etalonTag"].Value <int>();
                int[] excludeTags = config["excludeTags"]
                                    .Values <int>().ToArray();
                string[] excludePages = config["excludePages"]
                                        .Values <string>().ToArray();

                using (IrbisProvider provider = ProviderManager
                                                .GetAndConfigureProvider(connectionString))
                    using (StreamWriter writer = TextWriterUtility.Create
                                                 (
                               outputFileName,
                               IrbisEncoding.Utf8
                                                 ))
                    {
                        FileSpecification specification = new FileSpecification
                                                          (
                            IrbisPath.MasterFile,
                            provider.Database,
                            "WS31.OPT"
                                                          );
                        IrbisOpt opt = IrbisOpt.LoadFromServer
                                       (
                            provider,
                            specification
                                       );
                        if (ReferenceEquals(opt, null))
                        {
                            throw new IrbisException("Can't load OPT file!");
                        }

                        int[] found = provider.Search(searchExpression);
                        Console.WriteLine("Found: {0}", found.Length);

                        foreach (int mfn in found)
                        {
                            MarcRecord record = provider.ReadRecord(mfn);
                            if (ReferenceEquals(record, null))
                            {
                                continue;
                            }
                            string title = record.FM(etalonTag);
                            if (string.IsNullOrEmpty(title))
                            {
                                continue;
                            }

                            string wsName = opt.SelectWorksheet(opt.GetWorksheet(record));
                            if (string.IsNullOrEmpty(wsName))
                            {
                                continue;
                            }
                            specification = new FileSpecification
                                            (
                                IrbisPath.MasterFile,
                                provider.Database,
                                wsName + ".ws"
                                            );
                            WsFile worksheet = WsFile.ReadFromServer
                                               (
                                provider,
                                specification
                                               );
                            if (ReferenceEquals(worksheet, null))
                            {
                                continue;
                            }

                            Console.WriteLine("MFN={0}: {1}", mfn, title);
                            writer.WriteLine("<h3>{0}</h3>", title);

                            string description = provider.FormatRecord(record, "@");
                            writer.WriteLine(description);

                            RecordField[] fields = record.Fields
                                                   .Where(field => !field.Tag.OneOf(excludeTags))
                                                   .ToArray();

                            writer.WriteLine
                            (
                                "<table border=\"1\" "
                                + "cellpadding=\"3\" "
                                + "cellspacing=\"0\" "
                                + ">"
                            );
                            writer.WriteLine
                            (
                                "<tr bgcolor=\"black\">"
                                + "<th style=\"color:white;text-align:left;\">Поле</th>"
                                + "<th style=\"color:white;text-align:left;\">Подполе</th>"
                                + "<th style=\"color:white;text-align:left;\">Значение</th>"
                                + "</tr>"
                            );
                            foreach (WorksheetPage page in worksheet.Pages)
                            {
                                if (page.Name.OneOf(excludePages))
                                {
                                    continue;
                                }

                                int[] tags = page.Items
                                             .Select(item => item.Tag)
                                             .Select(NumericUtility.ParseInt32)
                                             .ToArray();
                                if (!fields.Any(field => field.Tag.OneOf(tags)))
                                {
                                    continue;
                                }
                                writer.WriteLine
                                (
                                    "<tr><td colspan=\"3\"><b>Вкладка «{0}»</b></td></tr>",
                                    page.Name
                                );

                                foreach (WorksheetItem item in page.Items)
                                {
                                    if (string.IsNullOrEmpty(item.Tag))
                                    {
                                        continue;
                                    }

                                    int tag = NumericUtility.ParseInt32(item.Tag);
                                    if (tag <= 0)
                                    {
                                        continue;
                                    }

                                    RecordField[] itemFields = fields.GetField(tag);
                                    for (int i = 0; i < itemFields.Length; i++)
                                    {
                                        RecordField field = itemFields[i];
                                        title = item.Title;
                                        title = StringUtility.Sparse(title);
                                        if (i != 0)
                                        {
                                            title = string.Format
                                                    (
                                                "(повторение {0})",
                                                i + 1
                                                    );
                                        }
                                        int rowspan = 1;
                                        if (string.IsNullOrEmpty(field.Value))
                                        {
                                            rowspan = 1 + field.SubFields.Count;
                                        }
                                        writer.WriteLine
                                        (
                                            "<tr><td rowspan=\"{0}\" \"width=\"{1}\"><b>{2}</b></td><td colspan=\"2\"><b>{3}</b></td></tr>",
                                            rowspan,
                                            FirstWidth,
                                            field.Tag,
                                            HtmlText.Encode(title)
                                        );

                                        if (!string.IsNullOrEmpty(field.Value))
                                        {
                                            writer.WriteLine
                                            (
                                                "<tr><td colspan=\"2\">&nbsp;</td><td>{0}</td></tr>",
                                                HtmlText.Encode(field.Value)
                                            );
                                        }

                                        if (item.EditMode == "5")
                                        {
                                            string inputInfo = item.InputInfo
                                                               .ThrowIfNull("item.InputInfo");

                                            // Поле с подполями
                                            specification = new FileSpecification
                                                            (
                                                IrbisPath.MasterFile,
                                                provider.Database,
                                                inputInfo
                                                            );
                                            WssFile wss = WssFile.ReadFromServer
                                                          (
                                                provider,
                                                specification
                                                          );
                                            if (ReferenceEquals(wss, null))
                                            {
                                                Console.WriteLine
                                                (
                                                    "Can't load: " + inputInfo
                                                );
                                            }
                                            else
                                            {
                                                foreach (WorksheetItem line in wss.Items)
                                                {
                                                    char     code     = line.Tag.FirstChar();
                                                    SubField subField = field.GetFirstSubField(code);
                                                    if (!ReferenceEquals(subField, null))
                                                    {
                                                        writer.WriteLine
                                                        (
                                                            "<tr>"
                                                            + "<td width=\"{0}\"><b>{1}</b>: {2}</td>"
                                                            + "<td width=\"{3}\">{4}</td></tr>",
                                                            SecondWidth,
                                                            CharUtility.ToUpperInvariant(code),
                                                            HtmlText.Encode(line.Title),
                                                            ThirdWidth,
                                                            HtmlText.Encode(subField.Value)
                                                        );
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            writer.WriteLine("</table>");
                        }
                    }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }