Versuchen Sie, ruby-net-nntp und tmail im Jahr 2020 auszuführen

Einführung

Ich habe mich aus Gründen der Notwendigkeit entschieden, mit NNTP zu kommunizieren. Ich hätte meine eigene NNTP-Klasse verwenden können, die ich vor langer Zeit erstellt habe, aber ich habe mich für ruby-net-nntp entschieden, das Gemfile verwenden kann. In dieser Bibliothek werden Artikel in der TMail :: Mail-Klasse gespeichert, sodass bei der Bundle-Installation auch tmail-1.2.7.1 heruntergeladen wird.

Ich habe die Verwendung von net / nttp und die Probleme, die in tmail aufgetreten sind, zusammengefasst.

Umwelt & Vorarbeiten

Bibliothek herunterladen

Ich habe die folgenden Dateien vorbereitet.

source 'https://rubygems.org'
gem "ruby-net-nntp"

Laden Sie die Bibliothek mit dem Bundler herunter


$ bundle install --path lib
$ ls lib/ruby/2.5.0/gems/
log4r-1.1.10/  ruby-net-nntp-1.0.0/  tmail-1.2.7.1/

Beispielprogramm erstellen

Als ich versuchte, den Code auszuführen, stieß ich sofort auf einen Fehler.

Fehler aufgetreten

require "net/nntp"Beim Ausführen wird folgende Fehlermeldung angezeigt:

Reproduzieren Sie den Fehler von irb


$ irb
irb(main):001:0> require "rubygems"
=> false
irb(main):002:0> require "bundler/setup"
=> true
irb(main):003:0> require 'net/nntp'
Traceback (most recent call last):
       14: from /usr/bin/irb:11:in `<main>'
       ...
        2: from .../lib/ruby/2.5.0/gems/tmail-1.2.7.1/lib/tmail/utils.rb:110:in `<module:TMail>'
        1: from .../lib/ruby/2.5.0/gems/tmail-1.2.7.1/lib/tmail/utils.rb:117:in `<module:TextUtils>'
RegexpError (/.../n has a non escaped non ASCII character in non ASCII-8BIT script)

Dies ist [http://www.ownway.info/Blog/2011/09/-invalid-multibyte-escape.html - Wie wird das Problem behoben, dass im regulären Ausdruck ein ungültiger Multibyte-Escape-Fehler auftritt](http: // www. Es wird in ownway.info/Blog/2011/09/-invalid-multibyte-escape.html) erklärt.

Der Link zu Google in diesem Artikel funktioniert nicht, daher [https://www.ruby-forum.com/t/ruby-1-9-1-invalid-multibyte-escape-regexperror/164732](https: / Sie können die ursprüngliche Diskussion unter /www.ruby-forum.com/t/ruby-1-9-1-invalid-multibyte-escape-regexperror/164732) sehen.

Unterschied

Ersetzen Sie die Notation /../n, in der das Problem auftritt, einfach mit Regexp.new ().

tmail library diff


diff -ru tmail-1.2.7.1.orig/./lib/tmail/scanner_r.rb tmail-1.2.7.1/./lib/tmail/scanner_r.rb
--- tmail-1.2.7.1.orig/./lib/tmail/scanner_r.rb 2020-06-10 22:06:16.813972850 +0900
+++ tmail-1.2.7.1/./lib/tmail/scanner_r.rb      2020-06-11 11:17:51.741512220 +0900
@@ -63,24 +63,24 @@
     PATTERN_TABLE = {}
     PATTERN_TABLE['EUC'] =
       [
-        /\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n,
-        /\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n,
+        Regexp.new("\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+", nil, "n"),
+        Regexp.new("\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+", nil, "n"),
         quoted_with_iso2022,
         domlit_with_iso2022,
         comment_with_iso2022
       ] 
     PATTERN_TABLE['SJIS'] =
       [
-        /\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n,
-        /\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n,
+        Regexp.new("\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+", nil, "n"),
+        Regexp.new("\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+", nil, "n"),
         quoted_with_iso2022,
         domlit_with_iso2022,
         comment_with_iso2022
       ] 
     PATTERN_TABLE['UTF8'] =
       [
-        /\A(?:[#{atomchars}]+|#{utf8str})+/n,
-        /\A(?:[#{tokenchars}]+|#{utf8str})+/n,
+        Regexp.new("\A(?:[#{atomchars}]+|#{utf8str})+", nil, "n"),
+        Regexp.new("\A(?:[#{tokenchars}]+|#{utf8str})+", nil, "n"),
         quoted_without_iso2022,
         domlit_without_iso2022,
         comment_without_iso2022
@@ -258,4 +258,4 @@
   end

 end   # module TMail
-#:startdoc:
\ No newline at end of file
+#:startdoc:
diff -ru tmail-1.2.7.1.orig/./lib/tmail/utils.rb tmail-1.2.7.1/./lib/tmail/utils.rb
--- tmail-1.2.7.1.orig/./lib/tmail/utils.rb     2020-06-10 22:06:16.813972850 +0900
+++ tmail-1.2.7.1/./lib/tmail/utils.rb  2020-06-11 11:11:59.582616384 +0900
@@ -114,10 +114,11 @@
     lwsp         = %Q| \t\r\n|
     control      = %Q|\x00-\x1f\x7f-\xff|
 
-    CONTROL_CHAR  = /[#{control}]/n
-    ATOM_UNSAFE   = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n
-    PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
-    TOKEN_UNSAFE  = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n
+    ## reference: http://www.ownway.info/Blog/2011/09/-invalid-multibyte-escape.html
+    CONTROL_CHAR  = Regexp.new("[#{control}]", nil, "n")
+    ATOM_UNSAFE   = Regexp.new("[#{Regexp.quote aspecial}#{control}#{lwsp}]", nil, "n")
+    PHRASE_UNSAFE = Regexp.new("[#{Regexp.quote aspecial}#{control}]", nil, "n")
+    TOKEN_UNSAFE  = Regexp.new("[#{Regexp.quote tspecial}#{control}#{lwsp}]", nil, "n")
     
     # Returns true if the string supplied is free from characters not allowed as an ATOM
     def atom_safe?( str )
diff -ru tmail-1.2.7.1.orig/./lib/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb tmail-1.2.7.1/./lib/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb
--- tmail-1.2.7.1.orig/./lib/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb        2020-06-10 22:06:16.829961402 +0900
+++ tmail-1.2.7.1/./lib/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb     2020-06-11 11:18:58.457912881 +0900
@@ -36,7 +36,7 @@
   class UniversalDetector
     attr_accessor :result
     def initialize
-      @_highBitDetector = /[\x80-\xFF]/
+      @_highBitDetector = Regex.new("[\x80-\xFF]")
       @_escDetector = /(\033|\~\{)/
       @_mEscCharSetProber = nil
       @_mCharSetProbers = []

Versuchen Sie, tatsächlich auf den NNTP-Server zuzugreifen

Ich weiß nicht, ob es einen NetNews-Server mit offenem Zugriff gibt, aber der Code für den Zugriff auf INN 2.5.5 sieht folgendermaßen aus:

test.rb


#!/usr/bin/ruby

require "rubygems"
require "bundler/setup"
require 'net/nntp'

nntp = Net::NNTP.new
Net::NNTP.logger = Log4r::Logger.new("nntp")
nntp.host = "nntp.example.com"
nntp.port = 119 
welcome = nntp.connect
if Net::NNTP::OKResponse === welcome
  group_name = "misc.test"
  group_response = nntp.process(Net::NNTP::Group.new(group_name))
  listgroup_response = nntp.process(Net::NNTP::Listgroup.new(group_name))
  listgroup_response.list.each { |article_id|
    
  }
end

Korrespondenz mit verstümmelten Zeichen des Subjekts

Dies hat nichts mit Docker zu tun, daher werde ich es dem obigen Abschnitt hinzufügen. Für den Header der gespeicherten Nachricht haben einige Felder eine eindeutige Klasse, aber diejenigen, die keine bestimmte Verarbeitung ausführen, wie z. B. Betreff: haben ihre Werte in der Klasse ** UnstructuredHeader ** gespeichert.

In diesem Fall wird Decoder.decode aufgerufen, aber diese Implementierung führt dazu, dass NKF.nkf mit der Option "-mSj" aufgerufen wird (MIME-Decodierung + Shift-JIS-Eingabecodierung + ISO-2022-JP-Ausgabecodierung). ..

Da es ein Problem gibt, wenn die Implementierung von Decoder.decode korrigiert wird, wird das ausgelassene Argument verwendet und die Ausgabecodierung auf UTF8 gesetzt.

Darüber hinaus verwendet From: die Klasse ** AddressHeader **, die ** StructuredHeader ** erbt, sodass eine weitere Kennzahl erforderlich ist. Es gibt eine Überprüfungsroutine, die nur "jes" (ISO-2022-JP, EUC-JP, Shift-JIS) als Codierung vor dem Aufruf von nkf annimmt, sodass Sie in diesem Punkt auch die Decoder-Klasse ein wenig definieren können. Wird eingesetzt.

Zusätzliche Unterschiede zu tmail


diff -ur lib/ruby/2.5.0/gems/tmail-1.2.7.1.orig/lib/tmail/header.rb lib/ruby/2.5.0/gems/tmail-1.2.7.1/lib/tmail/header.rb
--- lib/ruby/2.5.0/gems/tmail-1.2.7.1.orig/lib/tmail/header.rb  2020-06-16 10:59:57.589086000 +0900
+++ lib/ruby/2.5.0/gems/tmail-1.2.7.1/lib/tmail/header.rb       2020-06-16 11:01:30.527304391 +0900
@@ -189,5 +189,5 @@
     end

     def parse
-      @body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''))
+      @body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''), 'w')
     end

     def isempty?
diff -ur lib/ruby/2.7.0/gems/tmail-1.2.7.1.orig/lib/tmail/encode.rb lib/ruby/2.7.0/gems/tmail-1.2.7.1/lib/tmail/encode.rb
--- lib/ruby/2.7.0/gems/tmail-1.2.7.1.orig/lib/tmail/encode.rb  2020-06-18 14:32:37.352341212 +0900
+++ lib/ruby/2.7.0/gems/tmail-1.2.7.1/lib/tmail/encode.rb       2020-06-18 14:45:57.637057274 +0900
@@ -128,7 +128,7 @@

     def initialize( dest, encoding = nil, eol = "\n" )
       @f = StrategyInterface.create_dest(dest)
-      @encoding = (/\A[ejs]/ === encoding) ? encoding[0,1] : nil
+      @encoding = (/\A[ejsw]/ === encoding) ? encoding[0,1] : nil
       @eol = eol
     end

diff -ur lib/ruby/2.7.0/gems/tmail-1.2.7.1.orig/lib/tmail/header.rb lib/ruby/2.7.0/gems/tmail-1.2.7.1/lib/tmail/header.rb
--- lib/ruby/2.7.0/gems/tmail-1.2.7.1.orig/lib/tmail/header.rb  2020-06-18 14:32:37.993666420 +0900
+++ lib/ruby/2.7.0/gems/tmail-1.2.7.1/lib/tmail/header.rb       2020-06-18 14:47:16.026796369 +0900
@@ -147,7 +147,7 @@

     def body
       ensure_parsed
-      v = Decoder.new(s = '')
+      v = Decoder.new(s = '', "w")
       do_accept v
       v.terminate
       s
@@ -225,7 +225,7 @@
       rescue SyntaxError
         if not save and mime_encoded? @body
           save = @body
-          @body = Decoder.decode(save)
+          @body = Decoder.decode(save, "w")
           retry
         elsif save
           @body = save

Wenn Sie einen Patch in einer Ruby-2.7-Umgebung wie Dockers Ruby: 2.7-Alpine Image oder Ubuntu 20.04 LTS anwenden, konvertieren Sie die Datei "2.5.0" in "2.7.0", bevor Sie sie verwenden.

2.7 Beispiel für eine Patch-Anwendung auf die Umgebung


$ sed -e 's/2.5.0/2.7.0/g' tmail.diff | patch -p0

In Dockerfile ist ein Fehler aufgetreten

Das Docker-Bild verwendet Ruby: 2.7-alpine. Es gab einige Fehler, von denen einige in Ruby-2.5 nicht erkennbar waren und einige auf den Versuch zurückzuführen waren, als Nicht-Root-Benutzer ausgeführt zu werden.

Die Docker-Datei ohne mehrstufigen Build usw. wird vorerst unten gezeigt. Im aktuellen Verzeichnis befindet sich ein Ruby-Sinatra-Vorlagencode, der von openapi-generator wie Gemfile und config.ru erstellt wurde.

Dockerfile


FROM ruby:2.7-alpine as rubydev

RUN apk --no-cache add tzdata bash ca-certificates make gcc libc-dev linux-headers build-base patch 

RUN mkdir /app
COPY . /app
WORKDIR /app

RUN cp /usr/local/include/ruby-2.7.0/ruby/defines.h /usr/local/include/ruby-2.7.0/defines.h

RUN bundle config path lib
RUN bundle install

ENV SINATRA_PORT 8080
EXPOSE $SINATRA_PORT

ADD run.sh /run.sh
RUN chmod +x /run.sh

RUN addgroup sinatra
RUN adduser -S -G sinatra sinatra
# RUN cp -r /root/.bundle /home/sinatra/.bundle
USER sinatra

ENTRYPOINT ["/run.sh"]

Das Problem, dass die native Erweiterung von tmail nicht mit ruby-2.7 kompiliert werden kann

Ein Fehler tritt auf, wenn define.h nicht kompiliert werden kann.

Fehler aufgetreten


Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
...
current directory: /app/lib/ruby/2.7.0/gems/tmail-1.2.7.1/ext/tmailscanner/tmail
make "DESTDIR="
make: *** No rule to make target '/usr/local/include/ruby-2.7.0/defines.h',
needed by 'tmailscanner.o'.  Stop.
...

Da define.h nicht am erwarteten Speicherort vorhanden ist, wurde es von cp unterstützt.

Problemumgehung zu Dockerfile hinzugefügt


RUN cp /usr/local/include/ruby-2.7.0/ruby/defines.h \
  /usr/local/include/ruby-2.7.0/defines.h

In der Umgebung von Ubuntu 18.04 + ruby-2.5 (Deb-Paket) wurde ruby / defined.h am Ende von Makefile explizit angegeben, aber soweit ich Makefile von tmail in Dockerfile aktiviert habe, -I-Flag Es schien, dass nur /usr/local/include/ruby-2.7.0 in angegeben wurde.

ubuntu+ruby-2.5 Umgebungen


tmailscanner.o: tmailscanner.c $(hdrdir)/ruby/ruby.h $(arch_hdrdir)/ruby/config.h $(hdrdir)/ruby/defines.h Makefile

In der 2.7-alpinen Umgebung sollte define.h aus irgendeinem Grund ruby / defined.h sein.

2.7-Alpin Docker Bild


tmailscanner.o: tmailscanner.c $(hdrdir)/ruby.h $(arch_hdrdir)/ruby/config.h $(hdrdir)/defines.h Makefile

Das Problem ist mkmf.rb. In der Vorverarbeitung zum Ausschreiben der abhängigen Datei ist der Prozess zum Korrigieren der Zeile $ (hdrdir) /defines.h zu $ (hdrdir) ruby / defined.h ruby-2.7 mkmf. Es war, weil es in rb gelöscht wurde.

mkmf.rb


## ruby-2.5 mkmf.rb
   depend.each_line do |line|
      line.gsub!(/\.o\b/, ".#{$OBJEXT}")
      line.gsub!(/\{\$\(VPATH\)\}/, "") unless $nmake
      line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
      line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
      if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line

## ruby-2.7 mkmf.rb
    depend.each_line do |line|
      line.gsub!(/\.o\b/, ".#{$OBJEXT}")
      line.gsub!(/\{\$\(VPATH\)\}/, "") unless $nmake
      line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
      if $nmake && /\A\s*\$\(RM|COPY\)/

Es sieht aus wie eine Änderung, die unter https://github.com/ruby/ruby/commit/3d1c86a26f0c96a9c1d0247b968aa96e6f3c30bb#diff-7aa560cb6196deeb96779cd175e8e589 festgeschrieben wurde.

Es scheint, dass ich die Position von ruby.h korrigieren wollte, aber wahrscheinlich habe ich, anstatt die entsprechende Zeile zu löschen, eine gsub! -Zeile darunter hinzugefügt, die "ruby / ruby.h" in "ruby.h" umschreibt. Ich denke, ich hätte es tun sollen.

Es ist als https://bugs.ruby-lang.org/issues/16490 im Ruby's Issue Tracking System registriert, aber es scheint, dass die Überlegungen nicht voranschreiten.

Wenn Sie es mit Docker verwenden, gibt es keine andere Möglichkeit, als eine entsprechende Problemumgehung zu finden, indem Sie den Speicherort von defined.h ändern, anstatt mkmf.rb zu patchen ...

Umgang mit Rackup nicht gefunden Fehler

In Ruby-2.5 habe ich $ bundle install --path lib``` verwendet, aber ich habe eine Warnung erhalten, die besagt, dass sie veraltet ist, und habe sie so geändert, dass sie $ bundle config path lib``` verwendet tun.

Aus diesem Grund hängt es vom Inhalt der Datei ~ / .bundle / config ab. Daher habe ich den Benutzer zur Laufzeit mit `` `USER sinatra``` geändert, sodass ein Fehler aufgetreten ist, da die Datei ~ / .bundle / config nicht vorhanden ist. tat.

Details des Fehlers


$ make docker-run
sudo docker run -it --rm -p 8080:8080 --name nntp-reader nntp-reader:latest
bundler: command not found: rackup
Install missing gem executables with `bundle install`
Makefile:43: recipe for target 'docker-run' failed
make: *** [docker-run] Error 127

Die folgenden Maßnahmen können zuerst in Betracht gezogen werden.

Problemumgehung 1-run.Zur Laufzeit mit sh auflösen


#!/bin/bash

bundle config path lib  ##Problemumgehung hinzugefügt
export SINATRA_PORT=${SINATRA_PORT:-8080}
bundle exec rackup --host 0.0.0.0 --port $SINATRA_PORT

Diesmal wurde die folgende Methode angewendet.

Problemumgehung 2-Auflösen beim Erstellen eines Bildes mit Dockerfile


RUN cp -r /root/.bundle /home/sinatra/.bundle

das ist alles

Recommended Posts

Versuchen Sie, ruby-net-nntp und tmail im Jahr 2020 auszuführen
Versuchen Sie, Selenuim 3.141.59 mit Eclipse (Java) auszuführen.
Versuchen Sie, AWS X-Ray in Java auszuführen
Versuchen Sie, MySql und Blazor mit Docker-Compose auszuführen
Versuchen Sie LetCode in Ruby-TwoSum
Implementieren Sie Thread in Java und versuchen Sie, die anonyme Klasse Lambda zu verwenden
Versuchen Sie, Yuma in Kinx zu implementieren
Versuchen Sie es mit RocksDB mit Java
Versuchen Sie, JavaScript in Java aufzurufen
Lassen Sie uns Spresense mit Java entwickeln (1)
Probieren Sie den Funktionstyp in Java aus! ①
Mock and Stub in RSpec
Versuchen Sie, C-Sprache und Swift in einem Projekt (OS X, Linux) zu mischen.