├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.md ├── app.rb └── config.ru /.gitignore: -------------------------------------------------------------------------------- 1 | db/* 2 | tmp/* 3 | *.log 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'sinatra' 3 | gem 'dragonfly' 4 | gem 'rmagick', :require => 'RMagick' 5 | gem 'data_mapper' 6 | 7 | group :production do 8 | gem 'pg' 9 | gem 'dm-postgres-adapter' 10 | end 11 | 12 | group :development, :test do 13 | gem 'sqlite3' 14 | gem 'dm-sqlite-adapter' 15 | end 16 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.3.5) 5 | bcrypt-ruby (3.1.2) 6 | data_mapper (1.2.0) 7 | dm-aggregates (~> 1.2.0) 8 | dm-constraints (~> 1.2.0) 9 | dm-core (~> 1.2.0) 10 | dm-migrations (~> 1.2.0) 11 | dm-serializer (~> 1.2.0) 12 | dm-timestamps (~> 1.2.0) 13 | dm-transactions (~> 1.2.0) 14 | dm-types (~> 1.2.0) 15 | dm-validations (~> 1.2.0) 16 | data_objects (0.10.13) 17 | addressable (~> 2.1) 18 | dm-aggregates (1.2.0) 19 | dm-core (~> 1.2.0) 20 | dm-constraints (1.2.0) 21 | dm-core (~> 1.2.0) 22 | dm-core (1.2.1) 23 | addressable (~> 2.3) 24 | dm-do-adapter (1.2.0) 25 | data_objects (~> 0.10.6) 26 | dm-core (~> 1.2.0) 27 | dm-migrations (1.2.0) 28 | dm-core (~> 1.2.0) 29 | dm-postgres-adapter (1.2.0) 30 | dm-do-adapter (~> 1.2.0) 31 | do_postgres (~> 0.10.6) 32 | dm-serializer (1.2.2) 33 | dm-core (~> 1.2.0) 34 | fastercsv (~> 1.5) 35 | json (~> 1.6) 36 | json_pure (~> 1.6) 37 | multi_json (~> 1.0) 38 | dm-sqlite-adapter (1.2.0) 39 | dm-do-adapter (~> 1.2.0) 40 | do_sqlite3 (~> 0.10.6) 41 | dm-timestamps (1.2.0) 42 | dm-core (~> 1.2.0) 43 | dm-transactions (1.2.0) 44 | dm-core (~> 1.2.0) 45 | dm-types (1.2.2) 46 | bcrypt-ruby (~> 3.0) 47 | dm-core (~> 1.2.0) 48 | fastercsv (~> 1.5) 49 | json (~> 1.6) 50 | multi_json (~> 1.0) 51 | stringex (~> 1.4) 52 | uuidtools (~> 2.1) 53 | dm-validations (1.2.0) 54 | dm-core (~> 1.2.0) 55 | do_postgres (0.10.13) 56 | data_objects (= 0.10.13) 57 | do_sqlite3 (0.10.13) 58 | data_objects (= 0.10.13) 59 | dragonfly (1.0.1) 60 | multi_json (~> 1.0) 61 | rack 62 | fastercsv (1.5.5) 63 | json (1.8.1) 64 | json_pure (1.8.1) 65 | multi_json (1.8.2) 66 | pg (0.17.1) 67 | rack (1.5.2) 68 | rack-protection (1.5.1) 69 | rack 70 | rmagick (2.13.2) 71 | sinatra (1.4.4) 72 | rack (~> 1.4) 73 | rack-protection (~> 1.4) 74 | tilt (~> 1.3, >= 1.3.4) 75 | sqlite3 (1.3.8) 76 | stringex (1.5.1) 77 | tilt (1.4.1) 78 | uuidtools (2.1.4) 79 | 80 | PLATFORMS 81 | ruby 82 | 83 | DEPENDENCIES 84 | data_mapper 85 | dm-postgres-adapter 86 | dm-sqlite-adapter 87 | dragonfly 88 | pg 89 | rmagick 90 | sinatra 91 | sqlite3 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image Cache Logger 2 | 3 | A simple tool to see when other services/clients like Gmail open an image and test if they are storing it within their cache. 4 | 5 | ## Running Demo 6 | 7 | Feel free to use this as a demo or in actual testing. 8 | 9 | Image link (replace slug with anything): 10 | http://cache-logger.herokuapp.com/change-me-to-anything 11 | 12 | To check the logs without opening the image, append a /log to the end: 13 | http://cache-logger.herokuapp.com/change-me-to-anything/log 14 | 15 | You can also do */destroy* to delete all logs from an image and */remove* to delete the last log, but will have to make those calls using curl: 16 | 17 | curl -X DELETE http://cache-logger.herokuapp.com/change-me-to-anything/destroy 18 | curl -X DELETE http://cache-logger.herokuapp.com/change-me-to-anything/remove 19 | 20 | ## Setup your own instance 21 | 22 | Assuming you have git, ruby, bundler, and heroku setup... you can simply do: 23 | 24 | git clone https://github.com/kale/image-cache-logger 25 | cd image-cache-logger 26 | bundle install 27 | heroku create 28 | git push heroku master 29 | 30 | ## License 31 | 32 | Copyright (c) 2013 Kale Davis 33 | 34 | Permission is hereby granted, free of charge, to any person obtaining 35 | a copy of this software and associated documentation files (the 36 | "Software"), to deal in the Software without restriction, including 37 | without limitation the rights to use, copy, modify, merge, publish, 38 | distribute, sublicense, and/or sell copies of the Software, and to 39 | permit persons to whom the Software is furnished to do so, subject to 40 | the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be 43 | included in all copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 46 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 47 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 48 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 49 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 50 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 51 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 | -------------------------------------------------------------------------------- /app.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | require 'dragonfly' 3 | require 'RMagick' 4 | require 'data_mapper' 5 | 6 | DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/db/app.db") 7 | app = Dragonfly.app 8 | 9 | Dragonfly.app.configure do 10 | plugin :imagemagick 11 | end 12 | 13 | class ImageLogger 14 | include DataMapper::Resource 15 | property :id, Serial 16 | property :slug, String 17 | property :data, Text 18 | property :created_at, DateTime 19 | end 20 | 21 | DataMapper.auto_upgrade! 22 | 23 | get '/' do 24 | "Create an image by just a string after the url." 25 | end 26 | 27 | get "/:slug" do |slug| 28 | background_colors = %w(#EEEEEE #F2F2F2 #F5B7AB #EE836E #FFE8AA #FEDE88 #C5E5DE #95D1C4 #B1E0EC #6DC5DC) 29 | 30 | ImageLogger.create(:slug => slug, :data => "#{Time.now.to_s}\n#{request.user_agent}\n#{request.ip}\n", :created_at => Time.now) 31 | logs = ImageLogger.all(:slug => slug) 32 | data = [] 33 | logs.each {|l| data << l['data']} 34 | Dragonfly.app.generate( 35 | :text, 36 | "#{slug}\n\n#{data.join("\n")}", 37 | "font-size" => 14, 38 | "padding" => '10', 39 | "background-color" => background_colors[rand(background_colors.count)] 40 | ).to_response(env) 41 | end 42 | 43 | get "/:slug/log" do |slug| 44 | logs = ImageLogger.all(:slug => slug) 45 | data = [] 46 | logs.each {|l| data << l['data'].gsub("\n", "
")} 47 | "#{data.join("
")}" 48 | end 49 | 50 | #remove all logs 51 | delete "/:slug/destroy" do |slug| 52 | logs = ImageLogger.all(:slug => slug) 53 | logs.destroy 54 | redirect "/#{slug}/log" 55 | end 56 | 57 | #remove the last log 58 | delete "/:slug/remove" do |slug| 59 | log = ImageLogger.last(:slug => slug) 60 | log.destroy 61 | redirect "/#{slug}/log" 62 | end 63 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require './app' 2 | run Sinatra::Application 3 | --------------------------------------------------------------------------------