Essayez d'exécuter ruby-net-nntp et tmail en 2020

introduction

J'ai décidé de communiquer avec NNTP en raison de la nécessité. J'aurais pu utiliser ma propre classe NNTP que j'ai créée il y a longtemps, mais j'ai décidé d'utiliser ruby-net-nntp, qui peut utiliser Gemfile. Cette bibliothèque stocke les articles dans la classe TMail :: Mail, donc l'installation du bundle téléchargera également tmail-1.2.7.1.

J'ai résumé l'utilisation de net / nttp et les problèmes survenus dans tmail.

Environnement et travaux préparatoires

Télécharger la bibliothèque

J'ai préparé les fichiers suivants.

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

Téléchargez la bibliothèque à l'aide du bundler


$ 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/

Créer un exemple de programme

Lorsque j'ai essayé d'exécuter le code, j'ai immédiatement rencontré une erreur.

Erreur rencontrée

require "net/nntp"Lorsque je cours, j'obtiens l'erreur suivante:

Reproduire l'erreur d'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)

Voici [http://www.ownway.info/Blog/2011/09/-invalid-multibyte-escape.html --Comment traiter le problème d'une erreur d'échappement multi-octets non valide dans l'expression régulière](http: // www. Il est expliqué dans ownway.info/Blog/2011/09/-invalid-multibyte-escape.html).

Le lien vers Google dans cet article ne fonctionne pas, donc [https://www.ruby-forum.com/t/ruby-1-9-1-invalid-multibyte-escape-regexperror/164732](https: / Vous pouvez voir la discussion originale sur /www.ruby-forum.com/t/ruby-1-9-1-invalid-multibyte-escape-regexperror/164732).

Différence

Remplacez la notation /../n où le problème se produit simplement avec Regexp.new ().

bibliothèque tmail 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 = []

Essayez d'accéder au serveur NNTP

Je ne sais pas s'il existe un serveur NetNews avec un accès ouvert, mais le code pour accéder à mon INN 2.5.5 ressemble à ceci:

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

Correspondance avec les caractères déformés du sujet

Cela n'a rien à voir avec Docker, je vais donc l'ajouter à la section ci-dessus. Pour l'en-tête du message stocké, certains champs ont une classe unique, mais ceux qui n'effectuent pas de traitement spécifique tel que Subject: ont leurs valeurs stockées dans la classe ** UnstructuredHeader **.

Dans ce cas, Decoder.decode est appelé, mais cette implémentation rend NKF.nkf appelé avec l'option "-mSj" (décodage MIME + encodage d'entrée Shift-JIS + encodage de sortie ISO-2022-JP). ..

Puisqu'il y a un problème si l'implémentation de Decoder.decode est corrigée, l'argument omis est utilisé et le codage de sortie est défini sur UTF8.

De plus, From: utilise la classe ** AddressHeader ** qui hérite de ** StructuredHeader **, une autre mesure est donc requise. Il existe une routine de contrôle qui suppose uniquement "jes" (ISO-2022-JP, EUC-JP, Shift-JIS) comme encodage avant d'appeler nkf, vous pouvez donc également définir un peu la classe Decoder sur ce point. Est mis en.

Différences supplémentaires avec 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

Lors de l'application d'un correctif dans un environnement ruby-2.7 tel que Ruby de Docker: image 2.7-alpine ou Ubuntu 20.04 LTS, convertissez le fichier "2.5.0" en "2.7.0" avant de l'utiliser.

2.7 Exemple d'application de patch à l'environnement


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

Erreur rencontrée dans Dockerfile

L'image Docker utilise ruby: 2.7-alpine. Il y avait des erreurs, dont certaines n'étaient pas apparentes dans ruby-2.5, et dont certaines venaient d'essayer de s'exécuter en tant qu'utilisateur non root.

Le Dockerfile sans build multi-étapes, etc. est affiché ci-dessous pour le moment. Dans le répertoire actuel, il y a un code de modèle ruby-sinatra créé par openapi-generator tel que Gemfile et config.ru.

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"]

Le problème que l'extension native de tmail ne peut pas être compilée avec ruby-2.7

Une erreur se produira si define.h ne peut pas être compilé.

Erreur rencontrée


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.
...

Puisque define.h n'existe pas à l'emplacement attendu, il a été pris en charge par cp.

Solution de contournement ajoutée à Dockerfile


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

Dans l'environnement d'Ubuntu 18.04 + ruby-2.5 (paquet deb), ruby / define.h a été explicitement spécifié à la fin de Makefile, mais pour autant que j'ai vérifié Makefile de tmail dans Dockerfile, -I flag Il semble que seul /usr/local/include/ruby-2.7.0 était spécifié dans.

ubuntu+ruby-2.5 environnements


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

Dans l'environnement 2.7-alpin, pour une raison quelconque, define.h devrait être ruby / define.h.

2.7-image de docker alpin


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

Le problème est mkmf.rb, dans le prétraitement pour écrire le fichier depend, le processus pour modifier la ligne qui est $ (hdrdir) /defines.h en $ (hdrdir) ruby / définit.h est ruby-2.7 mkmf. C'était parce qu'il a été supprimé dans rb.

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\)/

Cela ressemble à la modification validée sur https://github.com/ruby/ruby/commit/3d1c86a26f0c96a9c1d0247b968aa96e6f3c30bb#diff-7aa560cb6196deeb96779cd175e8e589.

Il semble que je voulais corriger l'emplacement de ruby.h, mais probablement au lieu de supprimer la ligne correspondante, j'ai ajouté une ligne gsub! En dessous qui réécrit "ruby / ruby.h" en "ruby.h" Je pense que j'aurais dû le faire.

Il est enregistré sous le nom https://bugs.ruby-lang.org/issues/16490 dans le système de suivi des problèmes de Ruby, mais il semble que l'examen ne progresse pas.

Lorsque vous l'utilisez avec Docker, il n'y a pas d'autre moyen que de prendre une solution de contournement correspondante en modifiant l'emplacement de define.h plutôt que de patcher mkmf.rb ...

Traitement de l'erreur de rackup not found

Dans ruby-2.5, j'ai utilisé $ bundle install --path lib, mais j'ai reçu un avertissement disant obsolète, donc je l'ai changé pour utiliser `` `` $ bundle config path lib Faire.

Pour cette raison, cela dépend du contenu du fichier ~ / .bundle / config, j'ai donc changé l'utilisateur au moment de l'exécution avec USER sinatra, donc j'ai rencontré une erreur car le fichier ~ / .bundle / config n'existe pas. fait.

Détails de l'erreur


$ 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

Les mesures suivantes peuvent être envisagées en premier.

Solution de contournement 1-run.Résoudre lors de l'exécution avec sh


#!/bin/bash

bundle config path lib  ##Solution de contournement ajoutée
export SINATRA_PORT=${SINATRA_PORT:-8080}
bundle exec rackup --host 0.0.0.0 --port $SINATRA_PORT

La méthode suivante a été adoptée cette fois.

Solution de contournement 2-Résoudre lors de la création d'une image avec Dockerfile


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

c'est tout

Recommended Posts

Essayez d'exécuter ruby-net-nntp et tmail en 2020
Essayez d'exécuter Selenuim 3.141.59 avec eclipse (java)
Essayez d'exécuter AWS X-Ray en Java
Essayez d'exécuter MySql et Blazor avec docker-compose
Essayez LetCode dans Ruby-TwoSum
Implémentez Thread en Java et essayez d'utiliser la classe anonyme Lambda
Essayez d'implémenter Yuma dans Kinx
Essayez d'utiliser RocksDB avec Java
Essayez d'appeler JavaScript en Java
Essayez de développer Spresense avec Java (1)
Essayez le type fonctionnel en Java! ①
Maquette et stub dans RSpec
Essayez de mélanger le langage C et Swift dans un seul projet (OS X, Linux)