|Home|Why Use?|Demos|About |Contact|Mail List |Group |Hpricot By Mr _Why |FAQ|Workbench|Workbench-RO|

Forgotten Password

Enter your email address in the field below and click 'Reset Password' to have instructions on how to retrieve your forgotten password emailed to you.



Source Code Which Serves This Page:

/views/layouts/application.rhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <%= render(:partial => "layouts/head") %>
<body>
<table id="t2" width="98%" border="0">
<tr id="t2r2">
<td id="t2r2c2" valign="top">
  <%= render(:partial => "layouts/t2r2c2") %>
</td> <!-- t2r2c2 end -->
<td id="t2r2c4" valign="top">
<%= render(:partial => "layouts/bcrmbs") %>
<%= yield %>
<hr />
<h3> Source Code Which Serves This Page: </h3>
<%= render(:partial => "layouts/show_source") %>
<hr />
<%= render(:partial => "layouts/bcrmbs") %>
<hr />
</td> <!-- t2r2c4 end -->
<td id="t2r2c6" class="hpricot-color" valign="top">
  <%= render(:partial => "layouts/t2r2c6") %>
</td> <!-- t2r2c6 end -->
</tr> <!-- t2r2 end -->
</table>  <!-- t2 end -->
</body>
</html>

/views/layouts/_head.haml

%head
  %meta{"http-equiv" => "Content-Type", :content => "text/html; charset=utf-8"}
  %title hpricot.com
  %link{:rel => "shortcut icon", :href => "/favicon.ico"}
  = javascript_include_tag("prototype")
  = javascript_include_tag("effects")
  = javascript_include_tag("dragdrop")
  = javascript_include_tag("controls")
  = javascript_include_tag("application")
  = active_scaffold_includes
  = stylesheet_link_tag("application")

/views/layouts/_t2r2c2.haml

/ _t2r2c2.haml
%td#t2r2c2.hpricot-color{:valign => "top"}
  %div.white-color
    %hr
    %a{:href => "/"}
      %img{:src => "/images/hpricot-small.png", :alt => "http://hpricot.com"}
    %hr
    %h2
      = bcrmb('<a href="/">http://hpricot.com</a>')
    %hr
    %p
      %b
        = bcrmb('<a href="/sttc/why_hpricot"> Why Learn/Use Hpricot?</a>')
    %p
      %b
        = bcrmb('<a href="/demos"> Hpricot Demonstrations</a>')
    %p
      %b
        = bcrmb('<a href="/demos/about"> About</a>')
    %p
      %b
        = bcrmb('<a href="/sttc/contact"> Contact</a>')
    %p
      %b
        = bcrmb('<a href="/sttc/maillist"> Mail List</a>')
    %p
      %b
        %a{:href => "http://groups.google.com/group/hpricot", :target => "hp"} http://groups.google.com/group/hpricot
    %p
      %b
        %a{:href => "http://code.whytheluckystiff.net/hpricot", :target => "hp"} http://code.whytheluckystiff.net/hpricot
    %hr
    %p= render(:partial => "layouts/login_status")
    %hr
    %p
      %b
        = bcrmb('<a href="/sttc/workbench_faq"> FAQ for Hpricot Workbench</a>')
    %p
      %b
        = bcrmb('<a href="/frgmnts"> An Hpricot Workbench</a>')
    %p
      %b
        = bcrmb('<a href="/asls/frgmnts"> Hpricot Workbench Public (Read-Only)</a>')
    %p
      %b
        %a{:href => "http://chrispederick.com/work/web-developer", :target => "wd"}
          Hpricot Development Aid:
          %br http://chrispederick.com/work/web-developer
    %p
      %b
        %a{:href => "http://www.getfirebug.com", :target => "wd"}
          Hpricot Development Aid:
          %br http://www.getfirebug.com
    %p
      %b
        %a{:href => "/hpricot_rdoc154/index.html", :target => "hp"} RDoc of Hpricot 0.6
    %p
      %b
        %a{:href => "/app/index.html", :target => "hp"} RDoc of hpricot.com
    %p
      %b
        = bcrmb('<a href="/sttc/disclaimer"> Disclaimer!</a>')
    %hr
    = render(:partial => "/layouts/built_with")
    %hr

/views/layouts/_show_source.rhtml

<%= show_code("views/layouts", "application.rhtml") -%>
<%= show_code("views/layouts", "_head.haml") -%>
<%= show_code("views/layouts", "_t2r2c2.haml") -%>
<%= show_code("views/layouts", "_show_source.rhtml") -%>
<%= show_code("../public/stylesheets/sass", "application.sass") -%>
<%= show_code("../config", "routes.rb") -%>

<%= show_code("controllers", "application.rb") -%>
<%= show_code("controllers", "#{params[:controller]}_controller.rb") -%>
<%= show_code("helpers", "application_helper.rb") -%>
<%= show_code("helpers", "#{params[:controller]}_helper.rb") -%>
<p />
The Hpricot Workbench makes use of these models:
<p />
<%= show_code("models", "exprtype.rb") -%>
<%= show_code("models", "stck.rb") -%>
<%= show_code("models", "frgmnt.rb") -%>
<%= show_code("models", "usr.rb") -%>

/../public/stylesheets/sass/application.sass

td
  :border-style solid
  :border-width 1px
  :border-color black


body
  :background-color white
  :width 98%

.hpricot-color
  :background-color #FF7700

.white-color
  :background-color white

a
  :text-decoration underline
  :color #335500
  :font-weight bold
a:hover
  :text-decoration underline
  :color #FF7700
  :background-color #FFFFFF
a:visited


.redstack
  :background-color red

.greenstack
  :background-color green

.bluestack
  :background-color blue

.yellowstack
  :background-color yellow

.orangestack
  :background-color orange

.whitestack
  :background-color white

.blackstack
  :background-color black

// frgmnt-frgtxt is out of control. I constrain it with scroll bars.
div.frgmnt-frgtxt
  :overflow scroll
  :height 200px
  :width 200px


// Make text message at end of frgtxt more noticeable
span.snipmsg
  :color #1F7F00
  :font-weight bold

// Code

code
  :font-size 120%
  :line-height 140%
  :background-color #ddd

pre
  :background #333
  :color #fffed8
  :border 1px inset #aaa
  :overflow auto
  :padding 3px 5px
  :margin 5px 0

pre code
  :background-color transparent
// Code End

/../config/routes.rb

ActionController::Routing::Routes.draw do |map|
  # The priority is based upon order of creation: first created -> highest priority.

  # Sample of regular route:
  # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
  # Keep in mind you can assign values other than :controller and :action

  # Sample of named route:
  # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
  # This route can be invoked with purchase_url(:id => product.id)

  # You can have the root of your site routed by hooking up ''
  # -- just remember to delete public/index.html.
  map.connect '', :controller => "demos", :action => "about"

  # Allow downloading Web Service WSDL as a file with an extension
  # instead of a file named 'wsdl'
  map.connect ':controller/service.wsdl', :action => 'wsdl'

  # Install the default route as the lowest priority.
  map.connect ':controller/:action/:id.:format'
  map.connect ':controller/:action/:id'
end

/controllers/application.rb

# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

require 'usr_system'
require 'rubygems'
require 'hpricot'
require 'open-uri'

class ApplicationController < ActionController::Base
  # Pick a unique cookie name to distinguish our session data from others'
  session :session_key => '_hp12_session_id'
  include ERB::Util
  include UsrSystem
  helper :usr
  before_filter :authenticate_usr
  # I help Hpricot
  Hpricot.buffer_size = 262144

  # Null out the parse() method of  WebAgent::CookieManager so it cannot save cookies
  module Tst
    class WebAgent::CookieManager
      # Empty parse method which nulls out the effect of the real parse()
      def parse x, y
        @index = "nada"
      end # parse
    end # class
  end # module

  # Method for rendering the HTML in a Fragment
  def rndr_frgmnt
    @somehtml = Frgmnt.find(params[:id]).frgtxt
    render(:layout => "layouts/layout4rndr")
  end # rndr_frgmnt

  protected

  # Returns raw HTML.  Usually it gets passed to get_my_hp_elem()
  def get_my_html_from_open_uri(u)
    hdrs = {"User-Agent"=>"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1", "Accept-Charset"=>"utf-8", "Connection"=>"Keep-Alive", "Accept"=>"text/html"}
    my_html = ""
    begin
      open(u, hdrs).each {|s| my_html << s}
    rescue
      my_html = "<html><body><p /><b>hello world</b></body></html>"
    end
    return my_html
  end # get_my_html_from_open_uri()

  # Returns an Hpricot object from HTML obtained by get_my_html_from_open_uri()
  def get_my_hp_elem(u)
    h0 = Hpricot(get_my_html_from_open_uri(u))
    # remove crap
    # (h0/"script").remove
    return h0
  end # get_my_hp_elem()

  # Repel users who manually tinker with id in the request URL
  def repel_them
    # I dont need to repel_them if id is nil
    return if (params[:id] == nil)

    # Get the model class loaded into an object which can also be a class
    myklass = self.active_scaffold_config.model
    # Use the object-class-beastie to run .find() against the id in the request URL
    the_obj = myklass.find(params[:id])
    # Find out who owns the_obj
    the_usr_id = the_obj.send(:usr_id)
    # Repel them if they dont own the object pointed to by the id in the request URL
    redirect_to("/") unless the_usr_id == session[:usr_id]
  end

end # class

/controllers/usr_controller.rb

class UsrController < ApplicationController
  layout  'application'

  skip_before_filter :authenticate_usr, :only => [ :login, :signup, :forgot_password ]

  def login
    return if generate_blank_form
    @usr = Usr.new(params['usr'])
    usr = Usr.authenticate(params['usr']['login'], params['usr']['password'])
    if usr
      @current_usr = usr
      session[:usr_id] = usr.id
      flash['notice'] = 'Login succeeded'
      redirect_back_or_default :action => 'welcome'
    else
      @login = params['usr']['login']
      flash['message'] = 'Login failed'
    end
  end

  def signup
    return if generate_blank_form
    @usr = Usr.new(
      :login => params['usr'][:login],
      :password => params['usr'][:password],
      :password_confirmation => params['usr'][:password_confirmation],
      :email => params['usr'][:email],
      :first_name => params['usr'][:first_name],
      :last_name => params['usr'][:last_name]
    )
    begin
      Usr.transaction do
        @usr.password_needs_confirmation = true
        if @usr.save
          key = @usr.generate_security_token
          url = url_for(:action => 'welcome')
          url += "?usr[id]=#{@usr.id}&key=#{key}"
          UsrNotify.deliver_signup(@usr, params['usr']['password'], url)
          flash['notice'] = 'Signup successful! Please check your registered email account to verify your account registration and continue with the login.'
          redirect_to :action => 'login'
        end
      end
    rescue Exception => ex
      report_exception ex
      flash['message'] = 'Error creating account: confirmation email not sent'
    end
  end

  def logout
    session[:usr_id] = nil
    @current_usr = nil
    redirect_to :action => 'login'
  end

  def change_password
    return if generate_filled_in
    params['usr'].delete('form')
    begin
      @usr.change_password(params['usr']['password'], params['usr']['password_confirmation'])
      @usr.save!
    rescue Exception => ex
      report_exception ex
      flash.now['message'] = 'Your password could not be changed at this time. Please retry.'
      render and return
    end
    begin
      UsrNotify.deliver_change_password(@usr, params['usr']['password'])
    rescue Exception => ex
      report_exception ex
    end

  end

  def forgot_password
    if authenticated_usr?
      flash['message'] = 'You are currently logged in. You may change your password now.'
      redirect_to :action => 'change_password'
      return
    end

    return if generate_blank_form

    if params['usr']['email'].empty?
      flash.now['message'] = 'Please enter a valid email address.'
    elsif (usr = Usr.find_by_email(params['usr']['email'])).nil?
      flash.now['message'] = "We could not find a usr with the email address #{CGI.escapeHTML(params['usr']['email'])}"
    else
      begin
        Usr.transaction do
          key = usr.generate_security_token
          url = url_for(:action => 'change_password')
          url += "?usr[id]=#{usr.id}&key=#{key}"
          UsrNotify.deliver_forgot_password(usr, url)
          flash['notice'] = "Instructions on resetting your password have been emailed to #{CGI.escapeHTML(params['usr']['email'])}."
          unless authenticated_usr?
            redirect_to :action => 'login'
            return
          end
          redirect_back_or_default :action => 'welcome'
        end
      rescue Exception => ex
        report_exception ex
        flash.now['message'] = "Your password could not be emailed to #{CGI.escapeHTML(params['usr']['email'])}"
      end
    end
  end

  def edit
    return if generate_filled_in
    if params['usr']['form']
      form = params['usr'].delete('form')
      begin
        case form
        when "edit"
          unclean_params = params['usr']
          usr_params = unclean_params.delete_if { |k,v| not Usr::CHANGEABLE_FIELDS.include?(k) }
          @usr.attributes = usr_params
          @usr.save
          flash.now['notice'] = "Usr has been updated."
        when "change_password"
          change_password
        when "delete"
          delete
        else
          raise "unknown edit action"
        end
      rescue Exception => ex
        logger.warn ex
        logger.warn ex.backtrace
      end
    end
  end

  def delete
    @usr = @current_usr || Usr.find_by_id( session[:usr_id] )
    begin
      @usr.update_attribute( :deleted, true )
      logout
    rescue Exception => ex
      flash.now['message'] = "Error: #{@ex}."
      redirect_back_or_default :action => 'welcome'
    end
  end

  def welcome
  end

  protected

  def protect?(action)
    if ['login', 'signup', 'forgot_password'].include?(action)
      return false
    else
      return true
    end
  end

  # Generate a template usr for certain actions on get
  def generate_blank_form
    case request.method
    when :get
      @usr = Usr.new
      render
      return true
    end
    return false
  end

  # Generate a template usr for certain actions on get
  def generate_filled_in
    @usr = @current_usr || Usr.find_by_id( session[:usr_id] )
    case request.method
    when :get
      render
      return true
    end
    return false
  end

  def report_exception( ex )
    logger.warn ex
    logger.warn ex.backtrace.join("\n")
  end

end # class

/helpers/application_helper.rb

# Methods in this helper are available to all templates in the application.
module ApplicationHelper

  # An Hpricot based breadcrumb helper.
  # Usage:
  # bcrmb("<a href='/x/y'>About</a> | <a href='/z'>Contact</a>")
  # Loads html into an hpricot and then swaps out any a-tag with a span-tag
  # if the a-tag-href matches the request.path
  def bcrmb(h)
    # get an hpricot from the input-html
    hp =  Hpricot(h)
    # Inside the hpricot, look for an a-tag containing the request.path
    hps = hp.search("a[@href=#{request.path}]")
    if (matched_a_tag = hps.first)
      # I hooked one, get it's text node
      txtnode = matched_a_tag.inner_text
      # Inside the hpricot, swap the a-tag with a span-tag
      matched_a_tag.swap("<span class='bcrmb'>#{txtnode}</span>")
    end
    # Pull html out of the hpricot.
    return hp.to_html
  end # bcrmb


  # Builds a simple a-element from URL
  def inputurl_column(record)
    "<a target='inputurl'  href='#{record.inputurl}'>#{record.inputurl}</a>"
  end # inputurl_column

  # Override the stck column so I can add color to it via CSS
  def stck_column(record)
    "<span class='#{record.stck.name}'>#{record.stck.name}</span>"
  end

  # Override the frgtxt column so I can add links to it and maybe show a subset of the data in it.
  def frgtxt_column(record)
    link_to_rndr = link_to("Render The HTML Below:", {:id => record, :action => "rndr_frgmnt", :controller => "frgmnts"}, {:target => "l"})
    # Use the ERB::Util.h() method below to make sure the HTML is displayed rather than rendered.
    # If they want to render, they can click the link.
    # Notice that I use .slice() to limit the amount of text sent back to the browser.
    # If they want to see all of the text they can .rndr_frgmnt() and use browser-view-source.
    myfrgtxt = (record.frgtxt || "nil")
    if (h(myfrgtxt).length > 1024)
      snipmsg = "<span class='snipmsg'>SNIPPED at character number 1024.  Use render and then browser-view-source to see all of it.</span>"
    else
      snipmsg = ""
    end # if
    return("<div class='frgmnt-frgtxt'> <hr />#{link_to_rndr}<hr />#{h(myfrgtxt.slice(0,1024))} <hr /> #{snipmsg} <hr /></div>")
  end # frgtxt_column()

  # I found this in the AS demo.  They use it to show ruby code which corresponds to scaffold views.
  # This helper is called in a partial here: app/views/layouts/_show_source.rhtml
  # Here is a sample line from app/views/layouts/_show_source.rhtml:
  # <%= show_code("controllers", "#{params[:controller]}_controller.rb") -%>
  def show_code(path, filename, comment = "")
    begin
      file = File.open("#{File.dirname __FILE__}/../../app/#{path}/#{filename}")
<<PRE_BLOCK
<h4>/#{path}/#{filename} #{comment}</h4>
<pre><code class=\"ruby\">#{file.read.gsub("<", "<").gsub(">", ">").strip}</code></pre>
PRE_BLOCK
    rescue
      "#{filename} is missing"
    end # begin, rescue
  end # show_code

end

/helpers/usr_helper.rb

module UsrHelper

  DEFAULT_HEAD_OPTIONS = {
    :notice => true,
    :message => true,
    :error => false
  }.freeze unless defined? DEFAULT_HEAD_OPTIONS 

  def title_helper
    "#{@controller.controller_class_name} #{@controller.action_name}"
  end

  def head_helper(label, options = {})
    notice = message = error = nil
    opts = DEFAULT_HEAD_OPTIONS.dup
    opts.update(options.symbolize_keys)
    s = "<h3>#{label}</h3>"
    if flash['notice'] and not opts[:notice].nil? and opts[:notice]
      notice = "<div><p>#{flash['notice']}</p></div>"
      s = s + notice
    end
    if flash['message'] and not opts[:message].nil? and opts[:message]
      message = "<div id=\"ErrorExplanation\"><p>#{flash['message']}</p></div>"
      s = s + message
    end
    if not opts[:error].nil? and opts[:error]
     error = error_messages_for('usr')
     if not error.nil?
       error = error + "<br/>"
       s = s + error
     end
   end
   return s
  end

end

The Hpricot Workbench makes use of these models:

/models/exprtype.rb

class Exprtype < ActiveRecord::Base

  # Associations should come after callbacks
  has_many :frgmnts
  # Validations come after associations
  validates_presence_of :name
  validates_uniqueness_of :name, :message => " is already being used.  Pick a different name."
end

/models/stck.rb

class Stck < ActiveRecord::Base

  # Associations should come after callbacks
  has_many :frgmnts
  # Validations come after associations
  validates_presence_of :name
  validates_uniqueness_of :name, :message => " is already being used.  Pick a different name."
end

/models/frgmnt.rb

class Frgmnt < ActiveRecord::Base
  acts_as_tree  :order => "name"
  # Associations should come after callbacks
  belongs_to :usr
  belongs_to :exprtype
  belongs_to :stck
  # Validations come after associations
  validates_presence_of :name
  validates_uniqueness_of :name, :message => " is already being used.  Pick a different name."

  protected

  def validate
    case
    # Ensure we have some input
    when (parent == nil and inputurl == nil)
      errors.add(:parent, ", and Input URL are all nil.  You need one.")
    # We only want 1 input
    when (parent != nil and inputurl != nil)
      errors.add(:parent, "and Input URL are both not nil.  A fragment needs 1 (and only 1!)")
    # We should not scrape ourself
    when (parent == self)
      errors.add(:parent, " == self.  Pick a different parent.")
    # The controller will set name = "record_usr_id_ne_session_usr_id" if
    # I try to update a record I do not own.
    when name == "record_usr_id_ne_session_usr_id"
      errors.add_to_base "You can only update your records, not other's records."
    # display-enumerable needs format like this: table.some-class,[1,5]
    when (exprtype.name == 'display-enumerable()' and  ((arg1 =~ /(.*)?(\,)(\[)(\d+)(,)(\d+)(\])$/) != 0))
      errors.add(:arg1, ' Problem. display-enumerable() needs format like this: table.some-class,[1,5]')
    end # case
  end # validate

end

/models/usr.rb

require 'digest/sha1'

# this model expects a certain database layout and its based on the name/login pattern.
class Usr < ActiveRecord::Base
  CHANGEABLE_FIELDS = ['first_name', 'last_name', 'email']
  attr_accessor :password_needs_confirmation

  after_save '@password_needs_confirmation = false'
  after_validation :crypt_password

  validates_presence_of :login, :on => :create
  validates_length_of :login, :within => 3..40, :on => :create
  validates_uniqueness_of :login, :on => :create
  validates_uniqueness_of :email, :on => :create

  validates_presence_of :password, :if => :validate_password?
  validates_confirmation_of :password, :if => :validate_password?
  validates_length_of :password, { :minimum => 5, :if => :validate_password? }
  validates_length_of :password, { :maximum => 40, :if => :validate_password? }

  # Associations should come after callbacks
  has_many :frgmnts


  def initialize(attributes = nil)
    super
    @password_needs_confirmation = false
  end

  def self.authenticate(login, pass)
    u = find( :first, :conditions => ["login = ? AND verified = TRUE AND deleted = FALSE", login])
    return nil if u.nil?
    find( :first, :conditions => ["login = ? AND salted_password = ? AND verified = TRUE", login, salted_password(u.salt, hashed(pass))])
  end

  def self.authenticate_by_token(id, token)
    # Allow logins for deleted accounts, but only via this method (and
    # not the regular authenticate call)
    logger.info "Attempting authorization of #{id} with #{token}"
    u = find( :first, :conditions => ["id = ? AND security_token = ?", id, token])
    if u
      logger.info "Authenticated by token: #{u.inspect}"
    else
      logger.info "Not authenticated" if u.nil?
    end
    return nil if (u.nil? or u.token_expired?)
    u.update_attributes :verified => true, :token_expiry => Clock.now
    return u
  end

  def token_expired?
    self.security_token and self.token_expiry and (Clock.now >= self.token_expiry)
  end

  def generate_security_token
    if self.security_token.nil? or self.token_expiry.nil? or (Clock.now.to_i + token_lifetime / 2) >= self.token_expiry.to_i
      token = new_security_token
      return token
    else
      return self.security_token
    end
  end

  def change_password(pass, confirm = nil)
    self.password = pass
    self.password_confirmation = confirm.nil? ? pass : confirm
    @password_needs_confirmation = true
  end

  def token_lifetime
    UsrSystem::CONFIG[:security_token_life_hours] * 60 * 60
  end

  # Help Active Scaffold display Usr objects.
  # ref: http://activescaffold.com/tutorials/to_label
  def to_label
    login
  end

  protected

  attr_accessor :password, :password_confirmation

  def validate_password?
    @password_needs_confirmation
  end

  def self.hashed(str)
    return Digest::SHA1.hexdigest("change-me--#{str}--")[0..39]
  end

  def crypt_password
    if @password_needs_confirmation
      write_attribute("salt", self.class.hashed("salt-#{Clock.now}"))
      write_attribute("salted_password", self.class.salted_password(salt, self.class.hashed(@password)))
    end
  end

  def new_security_token
    expiry = Time.at(Clock.now.to_i + token_lifetime)
    write_attribute('security_token', self.class.hashed(self.salted_password + Clock.now.to_i.to_s + rand.to_s))
    write_attribute('token_expiry', expiry)
    update_without_callbacks
    return self.security_token
  end

  def self.salted_password(salt, hashed_password)
    hashed(salt + hashed_password)
  end
end

|Home|Why Use?|Demos|About |Contact|Mail List |Group |Hpricot By Mr _Why |FAQ|Workbench|Workbench-RO|