Quick FTP server - ruby

I'm looking for a quick, configuration-less, FTP server. Something exactly like Serve or Rack_dav, but for FTP, which can publish a folder just by running a command.
Is there a gem or something to do such thing?
Solution
Based on Wayne's ftpd gem, I created a quick and easy-to-use gem called Purvey.

The ftpd gem supports TLS, and comes with a file system driver. Like em-ftpd, you supply a driver, but that driver doesn't need to do much. Here's a bare-minimum FTP server that accepts any username/password, and serves files out of a temporary directory:
require 'ftpd'
require 'tmpdir'
class Driver
def initialize(temp_dir)
#temp_dir = temp_dir
end
def authenticate(user, password)
true
end
def file_system(user)
Ftpd::DiskFileSystem.new(#temp_dir)
end
end
Dir.mktmpdir do |temp_dir|
driver = Driver.new(temp_dir)
server = Ftpd::FtpServer.new(driver)
server.start
puts "Server listening on port #{server.bound_port}"
gets
end
NOTE: This example allows an FTP client to upload, delete, rename, etc.
To enable TLS:
include Ftpd::InsecureCertificate
...
server.certfile_path = insecure_certfile_path
server.tls = :explicit
server.start
Disclosure: I am ftpd's author and current maintainer

take a look at this gem, a Lightweight FTP server framework built on the EventMachine
https://github.com/yob/em-ftpd

Related

OCRA missing submodules of libraries if rack/grape api endpoints aren't called

I'm trying to pack my REST app into into an executable with OCRA. I have a few gems required in my script:
require 'rack'
require 'rack/server'
require 'grape'
require 'grape-entity'
require 'rubygems'
I skip starting the server with this:
if not defined?(Ocra)
Rack::Server.start options
end
When I try to run my server.exe:
Temp/../server.rb:221:in `default_middleware_by_environment':
cannot load such file -- rack/content_length (LoadError)
Which means that it doesn't detect submodules of rack that exist, but aren't used and therefore not included. If I add a require 'rack/content_length' it continues with cannot load such file -- rack/chunkedEven` and so on.
When I interrupted my server by hand before I also had to call a few api endpoints to have everything included.
I think my options are either:
Tell OCRA to include all the submodules of rack and grape, but compiling that list is a bit time consuming and would increase the file size
I already tried ocra server.rb --gem-full=rack --gem-full=grape, which get my server started, but when calling the API 'rack/mount/strexp' is missing again..
Calling the API within my script, but I couldn't figure out how to do that. I can't add a block to Rack::Server.start options and it does only continue when I interrupt the server.
Any ideas to implement either option, or is there another solution?
If we run the rack app with a rack handler (webrick / thin / else), we can shutdown the server in another thread so that ocra can finish packing (not sure how to do same thing with Rack::Server).
app = Rack::Directory.new ENV['HOME'] # a sample app
handler = Rack::Handler.pick %w/ thin webrick /
handler.run app do |server|
# handler.run yields a server object,
# which we shutdown when ocra is packing
if ocra_is_packing # replace with proper condition
Thread.new { sleep 10; server.shutdown }
end
end
You may have to do something else (access the server etc.) to have ocra pack appropriate dependencies.

Ruby not connecting to IMAP account

I’m trying to write a Ruby script that goes through an IMAP server, and I have set this up as test case. For some reason, though, I can’t get it to actually find the port. I’ve even tried running getaddrinfo, with no luck. It simply won’t acknowledge the server’s existence.
require 'net/imap'
test = File.new "test.txt", 'w'
imap = Net::IMAP.new('imap.google.com', 993, usessl=true, certs=nil, verify=false)
imap.authenticate('LOGIN', 'user', 'pass')
imap.examine('Mail')
imap.search(["SMS"]).each do |msg|
test << msg
end
The server is imap.gmail.com or imap.googlemail.com

Logging to remote location

I'm writing a client application which runs on a users computer and sends various requests to a server.
What I'd like to do is make logs from the client programs available on the server so that issues can be easily detected.
So, what I was thinking was to make the client log to a remote location over http.
Is this a good idea and are there any gems or libraries that will facilitate this?
You could use DRb + Logger for this. Both are part of the Ruby standard library, so you don't even need to install any gems on either machine.
Here's how it works:
Remote Logging Machine
require 'drb'
require 'logger'
DRb.start_service 'druby://0.0.0.0:9000', Logger.new('foo.log', 'weekly')
DRb.thread.join
Machine Doing the Logging
require 'drb'
$log = DRbObject.new_with_uri 'druby://remote.server.ip:9000'
begin
$log.info "Hello World"
rescue DRb::DRbConnError => e
warn "Could not log because: #{e}"
# Optionally re-log the message somewhere else.
end
puts "Yay, still running!"
I just tested this between two machines 1500 miles apart, where the client machine is even behind NAT, and it worked flawlessly.

Ruby require a code snippet from github

Is there anyway to get Ruby's require statement to download a file from somewhere like github rather than just the local file system?
Update: Sorry I should have made the question clearer. I want to download a file that contains Ruby module and import it into my script rather than just downloading an image or some other arbitrary file within my script.
In other words something like this
require 'http:\\github.com\myrepo\snippet.rb'
puts 'hi'
By default, this is not possible. Also, it's not a good idea for security reasons.
You have a couple of alternatives. If the file you want to include is a Gem and Git repository, then you can use Bundler to download and package the dependency in your project. Then you'll be able to require the file directly in your source code.
This is the best and safest way to include an external dependency.
If you trust the source and you really know what you are doing, you can download the file using Net::HTTP (or any other HTTP library) and eval the body directly in your Ruby code.
You can package everything in a custom require_remote function.
You could download and eval it
require "open-uri"
alias :require_old :require
def require(path)
return false if $".include?(path)
unless path=~ /\Ahttp:\/\/
return require_old(path)
end
eval(open(path).read)
$"<< path
true
end
Be aware, this code has no error checking for network outages nonexisting files, ... . I also believe it is in general not a good idea to require libraries this way, there are security and reliability problems in this approach. But maybe you have a valid usecase for this.
you can include a remote gem from within Gemfiles then it will download when you run bundle install
After reading this question and answers I wanted something a little more bullet proof and verbose that used a paradigm of creating a local file from a repo and then requiring it, only if it didn't already exist locally already. The request for the repo version is explicit via the method repo_require. Used on files you control, this approach improves security IMO.
# try local load
def local_require(filename, relative_path)
relative_flname = File.join(relative_path, filename)
require_relative(relative_flname)
end
# try loading locally first, try repo version on load error
# caution: only use with files you control access to!
def repo_require(raw_repo_prefix, filename, relative_path = '')
local_require(filename, relative_path)
rescue LoadError => e
puts e.message
require 'open-uri'
tempdir = Dir.mktmpdir("repo_require-")
temp_flname = File.join(tempdir, File.basename(filename))
return false if $LOADED_FEATURES.include?(temp_flname)
remote_flname = File.join(raw_repo_prefix, filename)
puts "file not found locally, checking repo: #{remote_flname}"
begin
File.open(temp_flname, 'w') do |f|
f.write(URI.parse(remote_flname).read)
end
rescue OpenURI::HTTPError => e
raise "Error: Can't load #{filename} from repo: #{e.message} - #{remote_flname}"
end
require(temp_flname)
FileUtils.remove_entry(tempdir)
end
Then you could call repo_require like this:
repo_require('https://raw.githubusercontent.com/username/reponame/branch',
'filename', 'relative_path')
The relative_path would the the relative path you would use for the file if the repo was locally installed. For example, you may have something like require_relative '../lib/utils.rb'. In this example filename='lib/utils.rb' and relative_path='..'. This information allows the repo url to be constructed correctly as it does not use the relative path portion.

How to get ip address, referer, and user agent in ruby?

I want to log user's ip address, referer, and user agent.
In PHP, I can get them from the following variables:
$_SERVER['REMOTE_ADDR']
$_SERVER['HTTP_REFERER']
$_SERVER['HTTP_USER_AGENT']
How to get them in ruby?
PHP is embedded in a web server. Ruby is a general-purpose language: if you need a web server context, you'll have to install it yourself. Fortunately, it's easy.
One of the easiest ways to get started is with Sinatra. Install the gem:
gem install sinatra
Then create myapp.rb:
require 'sinatra'
get '/' do
request.user_agent
end
Start up the web server:
ruby -rubygems myapp.rb
Visit Sinatra's default URL: http://localhost:4567/
Et voilà.
You need the array request.env
request.env['REMOTE_ADDR']:
I'm assuming you by ruby you mean ruby on rails, the following link shows you how to access them:
http://techoctave.com/c7/posts/25-rails-request-environment-variables

Resources