w3c / epubcheck

The conformance checker for EPUB publications
https://www.w3.org/publishing/epubcheck/
BSD 3-Clause "New" or "Revised" License
1.66k stars 403 forks source link

File mode specification error: (wrong-type-argument listp ) #1565

Open goodboylqs opened 4 months ago

goodboylqs commented 4 months ago

when I open most of mine epub files (except one epub file can open normally) it gives message "File mode specification error: (wrong-type-argument listp \357\273\277)",and nomatter I set my coding-system utf-8 or delete all the coding-system configuration content in my init.el,it still gives same error message. my configuration for nov

(use-package nov
  :ensure t
  :config 
   (setq nov-unzip-program (executable-find "unzip"))
;; (setq nov-unzip-program (executable-find "bsdtar"))
;; (setq nov-unzip-args '("-xC" directory "-f" filename))

  (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
  (add-to-list 'auto-mode-alist '("\\.mobi\\'" . nov-mode))
  )

should I add nov-unzip-args when I use unzip for nov?

and the Backtrace content

Debugger entered--Lisp error: (wrong-type-argument listp )
  assoc-delete-all(nil  eq)
  assq-delete-all(nil )
  nov-save-place(nil 0 1)
  nov-clean-up()
  nov-mode()
  set-auto-mode-0(nov-mode nil)
  set-auto-mode--apply-alist((("\\.odc\\'" . archive-mode) ("\\.odf\\'" . archive-mode) ("\\.odi\\'" . archive-mode) ("\\.otp\\'" . archive-mode) ("\\.odp\\'" . archive-mode) ("\\.otg\\'" . archive-mode) ("\\.odg\\'" . archive-mode) ("\\.ots\\'" . archive-mode) ("\\.ods\\'" . archive-mode) ("\\.odm\\'" . archive-mode) ("\\.ott\\'" . archive-mode) ("\\.odt\\'" . archive-mode) ("\\.mobi\\'" . nov-mode) ("\\.epub\\'" . nov-mode) ("\\.[pP][dD][fF]\\'" . pdf-view-mode) ("\\.html?\\'" . web-mode) ("\\.djhtml\\'" . web-mode) ("\\.mustache\\'" . web-mode) ("\\.erb\\'" . web-mode) ("\\.as[cp]x\\'" . web-mode) ("\\.[agj]sp\\'" . web-mode) ("\\.tpl\\.php\\'" . web-mode) ("\\.phtml\\'" . web-mode) ("README\\.md\\'" . gfm-mode) ("\\.gv\\'" . graphviz-dot-mode) ("\\.dot\\'" . graphviz-dot-mode) ("/git-rebase-todo\\'" . git-rebase-mode) ("\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" . markdown-mode) ("\\.tsx?\\'" . typescript-mode) ("\\.gpg\\(~\\|\\.~[0-9]+~\\)?\\'" nil epa-file) ("\\.elc\\'" . elisp-byte-code-mode) ("\\.zst\\'" nil jka-compr) ("\\.dz\\'" nil jka-compr) ("\\.xz\\'" nil jka-compr) ("\\.lzma\\'" nil jka-compr) ("\\.lz\\'" nil jka-compr) ("\\.g?z\\'" nil jka-compr) ("\\.bz2\\'" nil jka-compr) ("\\.Z\\'" nil jka-compr) ("\\.vr[hi]?\\'" . vera-mode) ("\\(?:\\.\\(?:rbw?\\|ru\\|rake\\|thor\\|jbuilder\\|rabl\\|ge..." . ruby-mode) ("\\.re?st\\'" . rst-mode) ("\\.py[iw]?\\'" . python-mode) ("\\.m\\'" . octave-maybe-mode) ("\\.less\\'" . less-css-mode) ("\\.scss\\'" . scss-mode) ("\\.cs\\'" . csharp-mode) ("\\.awk\\'" . awk-mode) ("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode) ("\\.idl\\'" . idl-mode) ...) nil nil)
  set-auto-mode()
  normal-mode(t)
  after-find-file(nil t)
  find-file-noselect-1(#<buffer 非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library).epub> "~/Nutstore Files/Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森..." nil nil "~/Nutstore Files/Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森..." (1337868 66308))
  find-file-noselect("./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)...." nil nil nil)
  #f(compiled-function (filename &optional wildcards) "Edit file FILENAME.\n\\<minibuffer-local-map>Switch to a buffer visiting file FILENAME, creating one if none\nalready exists.\nInteractively, the default if you just type RET is the current directory,\nbut the visited file name is available through the minibuffer history:\ntype \\[next-history-element] to pull it into the minibuffer.\n\nThe first time \\[next-history-element] is used after Emacs prompts for the file name,\nthe result is affected by `file-name-at-point-functions', which by\ndefault try to guess the file name by looking at point in the current\nbuffer.  Customize the value of `file-name-at-point-functions' or set\nit to nil, if you want only the visited file name and the current\ndirectory to be available on first \\[next-history-element] request.\n\nYou can visit files on remote machines by specifying something\nlike /ssh:SOME_REMOTE_MACHINE:FILE for the file name.  You can\nalso visit local files as a different user by specifying\n/sudo::FILE for the file name.\nSee the Info node `(tramp)File name Syntax' in the Tramp Info\nmanual, for more about this.\n\nInteractively, or if WILDCARDS is non-nil in a call from Lisp,\nexpand wildcards (if any) and visit multiple files.  You can\nsuppress wildcard expansion by setting `find-file-wildcards' to nil.\n\n\\<global-map>To visit a file without any kind of conversion and without\nautomatically choosing a major mode, use \\[find-file-literally]." (interactive #f(compiled-function () #<bytecode -0xbb586c647538781>)) #<bytecode -0x1cd75cdccbfd3287>)("./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)...." nil)
  apply(#f(compiled-function (filename &optional wildcards) "Edit file FILENAME.\n\\<minibuffer-local-map>Switch to a buffer visiting file FILENAME, creating one if none\nalready exists.\nInteractively, the default if you just type RET is the current directory,\nbut the visited file name is available through the minibuffer history:\ntype \\[next-history-element] to pull it into the minibuffer.\n\nThe first time \\[next-history-element] is used after Emacs prompts for the file name,\nthe result is affected by `file-name-at-point-functions', which by\ndefault try to guess the file name by looking at point in the current\nbuffer.  Customize the value of `file-name-at-point-functions' or set\nit to nil, if you want only the visited file name and the current\ndirectory to be available on first \\[next-history-element] request.\n\nYou can visit files on remote machines by specifying something\nlike /ssh:SOME_REMOTE_MACHINE:FILE for the file name.  You can\nalso visit local files as a different user by specifying\n/sudo::FILE for the file name.\nSee the Info node `(tramp)File name Syntax' in the Tramp Info\nmanual, for more about this.\n\nInteractively, or if WILDCARDS is non-nil in a call from Lisp,\nexpand wildcards (if any) and visit multiple files.  You can\nsuppress wildcard expansion by setting `find-file-wildcards' to nil.\n\n\\<global-map>To visit a file without any kind of conversion and without\nautomatically choosing a major mode, use \\[find-file-literally]." (interactive #f(compiled-function () #<bytecode -0xbb586c647538781>)) #<bytecode -0x1cd75cdccbfd3287>) "./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)...." nil)
  (if (and (file-directory-p file) (require 'eaf-file-manager nil t)) (eaf-open-in-file-manager file) (apply orig-fn file args))
  (if diredp (funcall orig-fn) (if (and (file-directory-p file) (require 'eaf-file-manager nil t)) (eaf-open-in-file-manager file) (apply orig-fn file args)))
  (if (eaf--find-file-ext-p ext) (cond ((string-equal ext "svg") (if (y-or-n-p (format "Open '%s' with EAF? " file)) (apply fn file nil) (find-file-literally file))) ((member ext '("docx" "doc" "ppt" "pptx" "xlsx" "xls")) (eaf-open-office file)) (t (apply fn file nil))) (if diredp (funcall orig-fn) (if (and (file-directory-p file) (require 'eaf-file-manager nil t)) (eaf-open-in-file-manager file) (apply orig-fn file args))))
  (let ((fn (if (commandp 'eaf-open) #'(lambda (file) (eaf-open file)) orig-fn)) (ext (file-name-extension file))) (if (eaf--find-file-ext-p ext) (cond ((string-equal ext "svg") (if (y-or-n-p (format "Open '%s' with EAF? " file)) (apply fn file nil) (find-file-literally file))) ((member ext '("docx" "doc" "ppt" "pptx" "xlsx" "xls")) (eaf-open-office file)) (t (apply fn file nil))) (if diredp (funcall orig-fn) (if (and (file-directory-p file) (require 'eaf-file-manager nil t)) (eaf-open-in-file-manager file) (apply orig-fn file args)))))
  eaf--find-file(#f(compiled-function (filename &optional wildcards) "Edit file FILENAME.\n\\<minibuffer-local-map>Switch to a buffer visiting file FILENAME, creating one if none\nalready exists.\nInteractively, the default if you just type RET is the current directory,\nbut the visited file name is available through the minibuffer history:\ntype \\[next-history-element] to pull it into the minibuffer.\n\nThe first time \\[next-history-element] is used after Emacs prompts for the file name,\nthe result is affected by `file-name-at-point-functions', which by\ndefault try to guess the file name by looking at point in the current\nbuffer.  Customize the value of `file-name-at-point-functions' or set\nit to nil, if you want only the visited file name and the current\ndirectory to be available on first \\[next-history-element] request.\n\nYou can visit files on remote machines by specifying something\nlike /ssh:SOME_REMOTE_MACHINE:FILE for the file name.  You can\nalso visit local files as a different user by specifying\n/sudo::FILE for the file name.\nSee the Info node `(tramp)File name Syntax' in the Tramp Info\nmanual, for more about this.\n\nInteractively, or if WILDCARDS is non-nil in a call from Lisp,\nexpand wildcards (if any) and visit multiple files.  You can\nsuppress wildcard expansion by setting `find-file-wildcards' to nil.\n\n\\<global-map>To visit a file without any kind of conversion and without\nautomatically choosing a major mode, use \\[find-file-literally]." (interactive #f(compiled-function () #<bytecode -0xbb586c647538781>)) #<bytecode -0x1cd75cdccbfd3287>) "./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)...." nil nil)
  eaf--find-file-advisor(#f(compiled-function (filename &optional wildcards) "Edit file FILENAME.\n\\<minibuffer-local-map>Switch to a buffer visiting file FILENAME, creating one if none\nalready exists.\nInteractively, the default if you just type RET is the current directory,\nbut the visited file name is available through the minibuffer history:\ntype \\[next-history-element] to pull it into the minibuffer.\n\nThe first time \\[next-history-element] is used after Emacs prompts for the file name,\nthe result is affected by `file-name-at-point-functions', which by\ndefault try to guess the file name by looking at point in the current\nbuffer.  Customize the value of `file-name-at-point-functions' or set\nit to nil, if you want only the visited file name and the current\ndirectory to be available on first \\[next-history-element] request.\n\nYou can visit files on remote machines by specifying something\nlike /ssh:SOME_REMOTE_MACHINE:FILE for the file name.  You can\nalso visit local files as a different user by specifying\n/sudo::FILE for the file name.\nSee the Info node `(tramp)File name Syntax' in the Tramp Info\nmanual, for more about this.\n\nInteractively, or if WILDCARDS is non-nil in a call from Lisp,\nexpand wildcards (if any) and visit multiple files.  You can\nsuppress wildcard expansion by setting `find-file-wildcards' to nil.\n\n\\<global-map>To visit a file without any kind of conversion and without\nautomatically choosing a major mode, use \\[find-file-literally]." (interactive #f(compiled-function () #<bytecode -0xbb586c647538781>)) #<bytecode -0x1cd75cdccbfd3287>) "./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)....")
  apply(eaf--find-file-advisor #f(compiled-function (filename &optional wildcards) "Edit file FILENAME.\n\\<minibuffer-local-map>Switch to a buffer visiting file FILENAME, creating one if none\nalready exists.\nInteractively, the default if you just type RET is the current directory,\nbut the visited file name is available through the minibuffer history:\ntype \\[next-history-element] to pull it into the minibuffer.\n\nThe first time \\[next-history-element] is used after Emacs prompts for the file name,\nthe result is affected by `file-name-at-point-functions', which by\ndefault try to guess the file name by looking at point in the current\nbuffer.  Customize the value of `file-name-at-point-functions' or set\nit to nil, if you want only the visited file name and the current\ndirectory to be available on first \\[next-history-element] request.\n\nYou can visit files on remote machines by specifying something\nlike /ssh:SOME_REMOTE_MACHINE:FILE for the file name.  You can\nalso visit local files as a different user by specifying\n/sudo::FILE for the file name.\nSee the Info node `(tramp)File name Syntax' in the Tramp Info\nmanual, for more about this.\n\nInteractively, or if WILDCARDS is non-nil in a call from Lisp,\nexpand wildcards (if any) and visit multiple files.  You can\nsuppress wildcard expansion by setting `find-file-wildcards' to nil.\n\n\\<global-map>To visit a file without any kind of conversion and without\nautomatically choosing a major mode, use \\[find-file-literally]." (interactive #f(compiled-function () #<bytecode -0xbb586c647538781>)) #<bytecode -0x1cd75cdccbfd3287>) "./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)....")
  find-file("./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)....")
  (if 'nil (find-file-other-window file) (find-file file))
  (if nil (if 'nil (dired-other-window file) (switch-to-buffer (dired file))) (if 'nil (find-file-other-window file) (find-file file)) (ffip--forward-line nil) (if nil (funcall nil file)))
  (lambda (file) (if nil (if 'nil (dired-other-window file) (switch-to-buffer (dired file))) (if 'nil (find-file-other-window file) (find-file file)) (ffip--forward-line nil) (if nil (funcall nil file))))("./Zotero-Library/书/非暴力沟通 ((美)马歇尔·卢森堡) (Z-Library)....")

and the nov unzip buffer content

Usage: unzip [-Z] [-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]
  Default action is to extract files in list, except those in xlist, to exdir;
  file[.zip] may be a wildcard.  -Z => ZipInfo mode ("unzip -Z" for usage).

  -p  extract files to pipe, no messages     -l  list files (short format)
  -f  freshen existing files, create none    -t  test compressed archive data
  -u  update files, create if necessary      -z  display archive comment only
  -v  list verbosely/show version info       -T  timestamp archive to latest
  -x  exclude files that follow (in xlist)   -d  extract files into exdir
modifiers:
  -n  never overwrite existing files         -q  quiet mode (-qq => quieter)
  -o  overwrite files WITHOUT prompting      -a  auto-convert any text files
  -j  junk paths (do not make directories)   -aa treat ALL files as text
  -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields
  -C  match filenames case-insensitively     -L  make (some) names lowercase
  -X  restore UID/GID info                   -V  retain VMS version numbers
  -K  keep setuid/setgid/tacky permissions   -M  pipe through "more" pager
  -O CHARSET  specify a character encoding for DOS, Windows and OS/2 archives
  -I CHARSET  specify a character encoding for UNIX and other archives
See "unzip -hh" or unzip.txt for more help.  Examples:
  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip
  unzip -p foo | more  => send contents of foo.zip via pipe into program more
  unzip -fo foo ReadMe => quietly replace existing ReadMe if archive file newer
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

when I open the epub file like '围城.epub' , the buffer 围城.epub picture below 截图_选择区域_20240707163719

I use C-x k ti kill buffer 围城.epub but not work,and Backtrace content below

Debugger entered--Lisp error: (wrong-type-argument listp )
  assoc-delete-all(nil  eq)
  assq-delete-all(nil )
  nov-save-place(nil 0 1)
  nov-clean-up()
  kill-buffer(#<buffer 围城.epub>)
  kill-this-buffer()
  funcall-interactively(kill-this-buffer)
  call-interactively(kill-this-buffer nil nil)
  command-execute(kill-this-buffer)

update: I found that maybe the epub file content type not correct which it has BOM(Byte Order Mark),so I use remove_bom_from_epub.py to adjust epub file content type,it still not work but the epub file picture is like this: 截图_holo_layer py_20240707165130

#remove_bom_from_epub.py
import os
import zipfile

def remove_bom_from_file(file_path):
    with open(file_path, 'rb') as file:
        content = file.read()
    if content.startswith(b'\xef\xbb\xbf'):
        content = content[3:]
    with open(file_path, 'wb') as file:
        file.write(content)

def process_epub(epub_path):
    # 解压缩EPUB文件
    with zipfile.ZipFile(epub_path, 'r') as zip_ref:
        extract_path = epub_path.replace('.epub', '')
        zip_ref.extractall(extract_path)

    # 遍历解压缩的文件夹,处理所有文件
    for root, dirs, files in os.walk(extract_path):
        for file in files:
            file_path = os.path.join(root, file)
            remove_bom_from_file(file_path)

    # 重新打包成EPUB文件
    new_epub_path = epub_path.replace('.epub', '_no_bom.epub')
    with zipfile.ZipFile(new_epub_path, 'w') as zip_ref:
        for root, dirs, files in os.walk(extract_path):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, extract_path)
                zip_ref.write(file_path, arcname)

    # 删除解压缩的临时文件夹
    for root, dirs, files in os.walk(extract_path, topdown=False):
        for file in files:
            os.remove(os.path.join(root, file))
        for dir in dirs:
            os.rmdir(os.path.join(root, dir))
    os.rmdir(extract_path)

    print(f'Processed EPUB saved as {new_epub_path}')

# 调用函数
process_epub('围城 出版七十周年纪念版 (钱锺书) (Z-Library).epub')

Backtrace

Debugger entered--Lisp error: (wrong-type-argument listp )
  assoc-delete-all(nil  eq)
  assq-delete-all(nil )
  nov-save-place(nil 0 1878)
  nov-clean-up()
  kill-all-local-variables()
  special-mode()
  nov-mode()
  funcall-interactively(nov-mode)
  call-interactively(nov-mode record nil)
  command-execute(nov-mode record)
  counsel-M-x-action("nov-mode")
  ivy-call()
  ivy-read("M-x " ("toggle-debug-on-error" "mpvi-open" "eval-defun" "mpvi-clip" "deft" "centaur-tabs-mode" "package-delete" "holo-layer-restart-process" "eval-buffer" "auto-package-update-now" "cd" "rg" "5x5" "amx" "arp" "dbx" "dig" "erc" "ert" "eww" "ftp" "gdb" "irc" "jdb" "lsp" "man" "mpc" "pdb" "pwd" "rsh" "sdb" "wos" "xdb" "calc" "diff" "dirs" "emms" "ffap" "ffip" "gnus" "grep" "help" "ielm" "info" "life" "mail" "mpuz" "ping" "pong" "talk" ...) :predicate counsel--M-x-externs-predicate :require-match t :history counsel-M-x-history :action counsel-M-x-action :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x)
  counsel-M-x()
  funcall-interactively(counsel-M-x)
  call-interactively(counsel-M-x nil nil)
  command-execute(counsel-M-x)
naglis commented 4 months ago

Hello @goodboylqs, is this issue related to epubcheck? I could not find it being invoked.

goodboylqs commented 3 months ago

sorry naglis,I thought it is the repo of nov.el and it's a error about nov.el,sorry for put a error issue