/// <summary> /// Распаковка 1-го файла из zip архива ZipPath /// Возвращает: Строку string с данными распакованного файла, если была распаковка. Иначе - пустую строку /// </summary> /// <param name="ZipPath">Путь к исходному zip-файлу</param> public string UnZipFB2FileToString(string ZipPath) { if (FilesWorker.isFB2Archive(ZipPath)) { MemoryStream ms = new MemoryStream(); ICSharpCode.SharpZipLib.Zip.ZipInputStream zis = new ICSharpCode.SharpZipLib.Zip.ZipInputStream( new FileStream(ZipPath, FileMode.Open) ); if (zis.GetNextEntry() != null) { int size = 2048; byte[] data = new byte[2048]; while (true) { size = zis.Read(data, 0, data.Length); if (size > 0) { ms.Write(data, 0, size); } else { break; } } byte[] bdata = ms.ToArray(); return(Encoding.GetEncoding(getEncoding(bdata)).GetString(bdata)); } } return(string.Empty); }
/// <summary> /// Распаковка zip архива в Temp папку и получение пути к распакованному файлу /// </summary> /// <param name="SourceZipFBZPath">Путь к исходному zip или fbz-файлу</param> /// <param name="TempDir">Временный каталог для распаковки архива</param> /// <returns>Путь к распакованному fb2 файлу из архива; null, если файл не является zip или fbz архивом, или не читается</returns> public static string getFileFromZipFBZ(string SourceZipFBZPath, string TempDir) { if (File.Exists(SourceZipFBZPath)) { if (!Directory.Exists(TempDir)) { Directory.CreateDirectory(TempDir); } if (FilesWorker.isFB2Archive(SourceZipFBZPath)) { return((m_sharpZipLib.UnZipFB2Files(SourceZipFBZPath, TempDir) > 0) ? Directory.GetFiles(TempDir)[0] : null); } } return(null); }
/// <summary> /// Сравнение 2-х файлов: fb2, fb2 из zip или fb2 из fbz /// </summary> /// <param name="DiffPath">Путь к diff-программе сравнения fb2 файла</param> /// <param name="FB2File1Path">Путь к 1-му исходному fb2, zip или fbz-файлу</param> /// <param name="FB2File2Path">Путь ко 2-му исходному fb2, zip или fbz-файлу</param> /// <param name="TempDirForFile1">Путь к временной папке для 1-го распакованного fb2 файла </param> /// <param name="TempDirForFile2">Путь к временной папке для 2-го распакованного fb2 файла </param> public static void DiffFB2(string DiffPath, string FB2File1Path, string FB2File2Path, string TempDirForFile1, string TempDirForFile2) { Cursor.Current = Cursors.WaitCursor; string TempFile1Path = null; string TempFile2Path = null; // создание путей (или распаковка) к исходным fb2 файлам, участвующим в сравнении if (FilesWorker.isFB2File(FB2File1Path)) { TempFile1Path = FB2File1Path; } else if (FilesWorker.isFB2Archive(FB2File1Path)) { TempFile1Path = getFileFromZipFBZ(FB2File1Path, TempDirForFile1); } if (FilesWorker.isFB2File(FB2File2Path)) { TempFile2Path = FB2File2Path; } else if (FilesWorker.isFB2Archive(FB2File2Path)) { TempFile2Path = getFileFromZipFBZ(FB2File2Path, TempDirForFile2); } // Сравнение файлов if (!string.IsNullOrWhiteSpace(TempFile1Path) && !string.IsNullOrWhiteSpace(TempFile2Path)) { FilesWorker.StartDiff(true, DiffPath, TempFile1Path, TempFile2Path); } // завершенн работы (перепаковка файла(ов), если он(они) были извлечены из архива) if (FilesWorker.isFB2Archive(FB2File1Path) && !string.IsNullOrWhiteSpace(TempFile1Path)) { WorksWithBooks.zipMoveTempFB2FileTo(m_sharpZipLib, TempFile1Path, FB2File1Path); } if (FilesWorker.isFB2Archive(FB2File2Path) && !string.IsNullOrWhiteSpace(TempFile2Path)) { WorksWithBooks.zipMoveTempFB2FileTo(m_sharpZipLib, TempFile2Path, FB2File2Path); } // удаление временных файлов, если они есть FilesWorker.RemoveDir(TempDirForFile1); FilesWorker.RemoveDir(TempDirForFile2); Cursor.Current = Cursors.Default; }
/// <summary> /// Правка fb2 и перепаковка fb2 из zip, fbz /// </summary> /// <param name="SourceFilePath">Путь к исходному fb2, zip или fbz-файлу</param> /// <param name="FB2ProgramPath">Путь к программе правки fb2 файла</param> public static void StartFB2_FBZForEdit(string SourceFilePath, string FB2ProgramPath) { Cursor.Current = Cursors.WaitCursor; if (FilesWorker.isFB2Archive(SourceFilePath)) { string TempFileFromZipPath = getFileFromZipFBZ(SourceFilePath, m_TempDir); if (!string.IsNullOrWhiteSpace(TempFileFromZipPath)) { FilesWorker.StartFile(true, FB2ProgramPath, TempFileFromZipPath); WorksWithBooks.zipMoveTempFB2FileTo(m_sharpZipLib, TempFileFromZipPath, SourceFilePath); FilesWorker.RemoveDir(m_TempDir); } } else { FilesWorker.StartFile(true, FB2ProgramPath, SourceFilePath); } Cursor.Current = Cursors.Default; }
/// <summary> /// Валидация fb2, fb2.zip ли fbz файлов по пути FilePath, согласно схеме SchemePath /// </summary> /// <returns>Пустая строка, файл валиден; Строка с сообщением, если файл невалиден</returns> private string validate(string FilePath, string SchemePath, ref bool IsZip) { string [] files = null; if (FilesWorker.isFB2Archive(FilePath)) { IsZip = true; _sharpZipLib.UnZipFB2Files(FilePath, _TempDir); files = Directory.GetFiles(_TempDir); } string FB2Path = (files != null && files.Length > 0) ? files[0] : FilePath; XmlDocument xmlDoc = new XmlDocument(); try { xmlDoc.Load(FB2Path); // Проверка наличия атрибутов корневого тега <FictionBook int FictionBookTagIndex = xmlDoc.InnerXml.IndexOf("<FictionBook", StringComparison.CurrentCulture); if (FictionBookTagIndex != -1) { Regex regex = new Regex("<FictionBook [^>]+>", RegexOptions.None); Match m = regex.Match(xmlDoc.InnerXml); if (m.Success) { string FBookTag = m.Value; int xmlnsIndex = FBookTag.IndexOf("xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.", StringComparison.CurrentCulture); int xmlnsLinkIndex = FBookTag.IndexOf("=\"http://www.w3.org/1999/xlink\"", StringComparison.CurrentCulture); if (xmlnsIndex == -1) { return("Файл: " + FilePath + "\r\nВ корневом теге <FictionBook отсутствует атрибут xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\""); } if (xmlnsLinkIndex == -1) { return("Файл: " + FilePath + "\r\nВ корневом теге <FictionBook отсутствует атрибут xmlns:l=\"http://www.w3.org/1999/xlink\""); } } } // Проверка обязательных тегов string TI = string.Empty; string DI = string.Empty; try { Regex regDesc = new Regex(@"<description>\s*?.+?\s*?</description>", RegexOptions.Multiline | RegexOptions.Singleline); Match mDesc = regDesc.Match(xmlDoc.InnerXml); if (mDesc.Success) { string Desc = mDesc.Value; Regex regTitleInfo = new Regex(@"<title-info>\s*?.+?\s*?</title-info>", RegexOptions.Multiline | RegexOptions.Singleline); Match mTI = regTitleInfo.Match(Desc); if (mTI.Success) { TI = mTI.Value; } Regex regDocumentInfo = new Regex(@"<document-info>\s*?.+?\s*?</document-info>", RegexOptions.Multiline | RegexOptions.Singleline); Match mDI = regDocumentInfo.Match(Desc); if (mDI.Success) { DI = mDI.Value; } } else { regDesc = new Regex("(?:<description[^/]+?(?:\"[^\"]*\"|'[^']*')?>)", RegexOptions.Multiline | RegexOptions.Singleline); mDesc = regDesc.Match(xmlDoc.InnerXml); return(mDesc.Success ? string.Format("Файл: {0}\r\nВ теге <description> присутствует(ет) аттрибут(ы), что недопустимо по стандарту FictionBook", FilePath) : string.Format("Файл: {0}\r\nОтсутствует раздел описания книги <description>", FilePath)); } } catch (RegexMatchTimeoutException /*ex*/) {} catch (Exception ex) { if (Settings.Settings.ShowDebugMessage) { // Показывать сообщения об ошибках при падении работы алгоритмов MessageBox.Show( string.Format("Ошибка алгоритмя Валидации:\r\n{0}", ex.Message), _MessageTitle, MessageBoxButtons.OK, MessageBoxIcon.Error ); } } if (!string.IsNullOrEmpty(TI)) { // Проверка <genre> if (TI.IndexOf("<genre", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <genre> книги", FilePath)); } else { Regex regGenre = new Regex(@"(<genre ?/>)|(<genre></genre>)", RegexOptions.None); Match mGenre = regGenre.Match(TI); if (mGenre.Success) { return(string.Format("Файл: {0}\r\nТег <genre> книги 'пустой'", FilePath)); } } // Проверка <lang> if (TI.IndexOf("<lang", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <lang> книги", FilePath)); } else { Regex regLang = new Regex(@"(<lang ?/>)|(<lang></lang>)", RegexOptions.None); Match mLang = regLang.Match(TI); if (mLang.Success) { return(string.Format("Файл: {0}\r\nТег <lang> книги 'пустой'", FilePath)); } else { regLang = new Regex(@"(?<=<lang>)[^<]+(?=</lang>)", RegexOptions.None); mLang = regLang.Match(TI); if (mLang.Success) { if (mLang.Value.Length > 2) { return(string.Format("Файл: {0}\r\nТег Название языка книги (тег <lang>) не может быть более 2 символов.\r\nЗначение тега <lang>: '{1}'", FilePath, mLang.Value)); } } } } // Проверка <author> if (TI.IndexOf("<author", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <author> Автора книги", FilePath)); } else { Regex regAuthor = new Regex(@"(<author ?/>)|(<author></author>)", RegexOptions.None); Match mAuthor = regAuthor.Match(TI); if (mAuthor.Success) { return(string.Format("Файл: {0}\r\nТег <author> Автора книги 'пустой'", FilePath)); } } // Проверка <book-title> if (TI.IndexOf("<book-title", StringComparison.CurrentCulture) == -1) { return(string.Format("Файл: {0}\r\nОтсутствует тег <book-title> Названия книги", FilePath)); } else { Regex regBT = new Regex(@"(<book-title ?/>)|(<book-title></book-title>)", RegexOptions.None); Match mBT = regBT.Match(TI); if (mBT.Success) { return(string.Format("Файл: {0}\r\nТег <book-title> Названия книги 'пустой'", FilePath)); } } } else { return(string.Format("Файл: {0}\r\nОтсутствует раздел описания книги <title-info>", FilePath)); } if (!string.IsNullOrEmpty(DI)) { // Проверка id книги if (DI.IndexOf("<id", StringComparison.CurrentCulture) == -1) { return("Файл: " + FilePath + "\r\nОтсутствует идентификатор книги тег <id>"); } else { Regex regID = new Regex(@"(<id ?/>)|(<id></id>)", RegexOptions.None); Match mID = regID.Match(DI); if (mID.Success) { return(string.Format("Файл: {0}\r\nИдентификатор книги тег <id> 'пустой'", FilePath)); } } } else { return(string.Format("Файл: {0}\r\nОтсутствует раздел описания книги <document-info>", FilePath)); } } catch (System.Exception e) { return(string.Format("{0}\r\n\r\nФайл: {1}", e.Message, FilePath)); } Cursor.Current = Cursors.WaitCursor; string fb2FileNamespaceURI = xmlDoc.DocumentElement.NamespaceURI; using (Stream xmlSchemeFile = new FileStream(SchemePath, FileMode.Open)) { XmlSchemaSet sc = new XmlSchemaSet(); try { if (fb2FileNamespaceURI.Equals(_aFB21Namespace)) { sc.Add(_aFB21Namespace, XmlReader.Create(xmlSchemeFile)); } else { sc.Add(_aFB20Namespace, XmlReader.Create(xmlSchemeFile)); } } catch (System.Xml.Schema.XmlSchemaException e) { return(string.Format("Файл: {0}\r\n{1}\r\nСтрока: {2}; Позиция: {3}", FilePath, e.Message, e.LineNumber, e.LinePosition)); } XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.Schemas = sc; XmlReader reader = XmlReader.Create(FB2Path, settings); try { while (reader.Read()) { ; } reader.Close(); Cursor.Current = Cursors.Default; return(string.Empty); } catch (System.Xml.Schema.XmlSchemaException e) { reader.Close(); Cursor.Current = Cursors.Default; return(string.Format("Файл: {0}\r\n{1}\r\nСтрока: {2}; Позиция: {3}", FilePath, e.Message, e.LineNumber, e.LinePosition)); } catch (System.Exception e) { reader.Close(); Cursor.Current = Cursors.Default; return(string.Format("Файл: {0}\r\n{1}", FilePath, e.Message)); } } }