$14 GRAYBYTE WORDPRESS FILE MANAGER $42

SERVER : premium201.web-hosting.com #1 SMP Wed Mar 26 12:08:09 UTC 2025
SERVER IP : 172.67.217.254 | ADMIN IP 216.73.216.157
OPTIONS : CRL = ON | WGT = ON | SDO = OFF | PKEX = OFF
DEACTIVATED : mail

/opt/cpanel/ea-ruby27/root/usr/share/gems/doc/rack-2.2.22/rdoc/Rack/Session/

HOME
Current File : /opt/cpanel/ea-ruby27/root/usr/share/gems/doc/rack-2.2.22/rdoc/Rack/Session//Cookie.html
<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">

<title>class Rack::Session::Cookie - rack-2.2.22 Documentation</title>

<script type="text/javascript">
  var rdoc_rel_prefix = "../../";
  var index_rel_prefix = "../../";
</script>

<script src="../../js/navigation.js" defer></script>
<script src="../../js/search.js" defer></script>
<script src="../../js/search_index.js" defer></script>
<script src="../../js/searcher.js" defer></script>
<script src="../../js/darkfish.js" defer></script>

<link href="../../css/fonts.css" rel="stylesheet">
<link href="../../css/rdoc.css" rel="stylesheet">




<body id="top" role="document" class="class">
<nav role="navigation">
  <div id="project-navigation">
    <div id="home-section" role="region" title="Quick navigation" class="nav-section">
  <h2>
    <a href="../../index.html" rel="home">Home</a>
  </h2>

  <div id="table-of-contents-navigation">
    <a href="../../table_of_contents.html#pages">Pages</a>
    <a href="../../table_of_contents.html#classes">Classes</a>
    <a href="../../table_of_contents.html#methods">Methods</a>
  </div>
</div>

    <div id="search-section" role="search" class="project-section initially-hidden">
  <form action="#" method="get" accept-charset="utf-8">
    <div id="search-field-wrapper">
      <input id="search-field" role="combobox" aria-label="Search"
             aria-autocomplete="list" aria-controls="search-results"
             type="text" name="search" placeholder="Search" spellcheck="false"
             title="Type to search, Up and Down to navigate, Enter to load">
    </div>

    <ul id="search-results" aria-label="Search Results"
        aria-busy="false" aria-expanded="false"
        aria-atomic="false" class="initially-hidden"></ul>
  </form>
</div>

  </div>

  

  <div id="class-metadata">
    
    <div id="parent-class-section" class="nav-section">
  <h3>Parent</h3>

  
  <p class="link"><a href="Abstract/PersistedSecure.html">Rack::Session::Abstract::PersistedSecure</a>
  
</div>

    
    
    <!-- Method Quickref -->
<div id="method-list-section" class="nav-section">
  <h3>Methods</h3>

  <ul class="link-list" role="directory">
    
    <li class="calls-super" ><a href="#method-c-new">::new</a>
    
    <li ><a href="#method-i-delete_session">#delete_session</a>
    
    <li ><a href="#method-i-digest_match-3F">#digest_match?</a>
    
    <li ><a href="#method-i-extract_session_id">#extract_session_id</a>
    
    <li ><a href="#method-i-find_session">#find_session</a>
    
    <li ><a href="#method-i-generate_hmac">#generate_hmac</a>
    
    <li ><a href="#method-i-persistent_session_id-21">#persistent_session_id!</a>
    
    <li ><a href="#method-i-secure-3F">#secure?</a>
    
    <li ><a href="#method-i-unpacked_cookie_data">#unpacked_cookie_data</a>
    
    <li ><a href="#method-i-write_session">#write_session</a>
    
  </ul>
</div>

  </div>
</nav>

<main role="main" aria-labelledby="class-Rack::Session::Cookie">
  <h1 id="class-Rack::Session::Cookie" class="class">
    class Rack::Session::Cookie
  </h1>

  <section class="description">
    
<p><a href="Cookie.html"><code>Rack::Session::Cookie</code></a> provides simple cookie based session management. By default, the session is a Ruby Hash stored as base64 encoded marshalled data set to :key (default: rack.session).  The object that encodes the session data is configurable and must respond to <code>encode</code> and <code>decode</code>. Both methods must take a string and return a string.</p>

<p>When the secret key is set, cookie data is checked for data integrity. The old secret key is also accepted and allows graceful secret rotation.</p>

<p>Example:</p>

<pre>use Rack::Session::Cookie, :key =&gt; &#39;rack.session&#39;,
                           :domain =&gt; &#39;foo.com&#39;,
                           :path =&gt; &#39;/&#39;,
                           :expire_after =&gt; 2592000,
                           :secret =&gt; &#39;change_me&#39;,
                           :old_secret =&gt; &#39;also_change_me&#39;

All parameters are optional.</pre>

<p>Example of a cookie with no encoding:</p>

<pre class="ruby"><span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Session</span><span class="ruby-operator">::</span><span class="ruby-constant">Cookie</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">application</span>, {
  <span class="ruby-value">:coder</span> <span class="ruby-operator">=&gt;</span> <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Session</span><span class="ruby-operator">::</span><span class="ruby-constant">Cookie</span><span class="ruby-operator">::</span><span class="ruby-constant">Identity</span>.<span class="ruby-identifier">new</span>
})
</pre>

<p>Example of a cookie with custom encoding:</p>

<pre class="ruby"><span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Session</span><span class="ruby-operator">::</span><span class="ruby-constant">Cookie</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">application</span>, {
  <span class="ruby-value">:coder</span> <span class="ruby-operator">=&gt;</span> <span class="ruby-constant">Class</span>.<span class="ruby-identifier">new</span> {
    <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">encode</span>(<span class="ruby-identifier">str</span>); <span class="ruby-identifier">str</span>.<span class="ruby-identifier">reverse</span>; <span class="ruby-keyword">end</span>
    <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">decode</span>(<span class="ruby-identifier">str</span>); <span class="ruby-identifier">str</span>.<span class="ruby-identifier">reverse</span>; <span class="ruby-keyword">end</span>
  }.<span class="ruby-identifier">new</span>
})
</pre>

  </section>

  
  <section id="5Buntitled-5D" class="documentation-section">
    

    

    

    
    <section class="attribute-method-details" class="method-section">
      <header>
        <h3>Attributes</h3>
      </header>

      
      <div id="attribute-i-coder" class="method-detail">
        <div class="method-heading attribute-method-heading">
          <span class="method-name">coder</span><span
            class="attribute-access-type">[R]</span>
        </div>

        <div class="method-description">
        
        
        
        </div>
      </div>
      
    </section>
    

    
     <section id="public-class-5Buntitled-5D-method-details" class="method-section">
       <header>
         <h3>Public Class Methods</h3>
       </header>

    
      <div id="method-c-new" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">new</span><span
            class="method-args">(app, options = {})</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          
            <div class="method-calls-super">
              Calls superclass method
              <a href="Abstract/Persisted.html#method-c-new"><code>Rack::Session::Abstract::Persisted::new</code></a>
            </div>
          

          
          <div class="method-source-code" id="new-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 107</span>
      <span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">initialize</span>(<span class="ruby-identifier">app</span>, <span class="ruby-identifier">options</span> = {})
        <span class="ruby-ivar">@secrets</span> = <span class="ruby-identifier">options</span>.<span class="ruby-identifier">values_at</span>(<span class="ruby-value">:secret</span>, <span class="ruby-value">:old_secret</span>).<span class="ruby-identifier">compact</span>
        <span class="ruby-ivar">@hmac</span> = <span class="ruby-identifier">options</span>.<span class="ruby-identifier">fetch</span>(<span class="ruby-value">:hmac</span>, <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">Digest</span><span class="ruby-operator">::</span><span class="ruby-constant">SHA1</span>)

        <span class="ruby-identifier">warn</span> <span class="ruby-identifier">&lt;&lt;-MSG</span> <span class="ruby-keyword">unless</span> <span class="ruby-identifier">secure?</span>(<span class="ruby-identifier">options</span>)
<span class="ruby-value">        SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
        This poses a security threat. It is strongly recommended that you
        provide a secret to prevent exploits that may be possible from crafted
        cookies. This will not be supported in future versions of Rack, and
        future versions will even invalidate your existing user cookies.

        Called from: #{caller[0]}.
</span><span class="ruby-identifier">        MSG</span>
        <span class="ruby-ivar">@coder</span> = <span class="ruby-identifier">options</span>[<span class="ruby-value">:coder</span>] <span class="ruby-operator">||=</span> <span class="ruby-constant">Base64</span><span class="ruby-operator">::</span><span class="ruby-constant">Marshal</span>.<span class="ruby-identifier">new</span>
        <span class="ruby-keyword">super</span>(<span class="ruby-identifier">app</span>, <span class="ruby-identifier">options</span>.<span class="ruby-identifier">merge!</span>(<span class="ruby-value">cookie_only:</span> <span class="ruby-keyword">true</span>))
      <span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
    </section>
  
     <section id="private-instance-5Buntitled-5D-method-details" class="method-section">
       <header>
         <h3>Private Instance Methods</h3>
       </header>

    
      <div id="method-i-delete_session" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">delete_session</span><span
            class="method-args">(req, session_id, options)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="delete_session-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 180</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">delete_session</span>(<span class="ruby-identifier">req</span>, <span class="ruby-identifier">session_id</span>, <span class="ruby-identifier">options</span>)
  <span class="ruby-comment"># Nothing to do here, data is in the client</span>
  <span class="ruby-identifier">generate_sid</span> <span class="ruby-keyword">unless</span> <span class="ruby-identifier">options</span>[<span class="ruby-value">:drop</span>]
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-digest_match-3F" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">digest_match?</span><span
            class="method-args">(data, digest)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="digest_match-3F-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 185</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">digest_match?</span>(<span class="ruby-identifier">data</span>, <span class="ruby-identifier">digest</span>)
  <span class="ruby-keyword">return</span> <span class="ruby-keyword">unless</span> <span class="ruby-identifier">data</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-identifier">digest</span>
  <span class="ruby-ivar">@secrets</span>.<span class="ruby-identifier">any?</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">secret</span><span class="ruby-operator">|</span>
    <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Utils</span>.<span class="ruby-identifier">secure_compare</span>(<span class="ruby-identifier">digest</span>, <span class="ruby-identifier">generate_hmac</span>(<span class="ruby-identifier">data</span>, <span class="ruby-identifier">secret</span>))
  <span class="ruby-keyword">end</span>
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-extract_session_id" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">extract_session_id</span><span
            class="method-args">(request)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="extract_session_id-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 132</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">extract_session_id</span>(<span class="ruby-identifier">request</span>)
  <span class="ruby-identifier">unpacked_cookie_data</span>(<span class="ruby-identifier">request</span>)[<span class="ruby-string">&quot;session_id&quot;</span>]
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-find_session" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">find_session</span><span
            class="method-args">(req, sid)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="find_session-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 126</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">find_session</span>(<span class="ruby-identifier">req</span>, <span class="ruby-identifier">sid</span>)
  <span class="ruby-identifier">data</span> = <span class="ruby-identifier">unpacked_cookie_data</span>(<span class="ruby-identifier">req</span>)
  <span class="ruby-identifier">data</span> = <span class="ruby-identifier">persistent_session_id!</span>(<span class="ruby-identifier">data</span>)
  [<span class="ruby-identifier">data</span>[<span class="ruby-string">&quot;session_id&quot;</span>], <span class="ruby-identifier">data</span>]
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-generate_hmac" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">generate_hmac</span><span
            class="method-args">(data, secret)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="generate_hmac-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 192</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">generate_hmac</span>(<span class="ruby-identifier">data</span>, <span class="ruby-identifier">secret</span>)
  <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">HMAC</span>.<span class="ruby-identifier">hexdigest</span>(<span class="ruby-ivar">@hmac</span>.<span class="ruby-identifier">new</span>, <span class="ruby-identifier">secret</span>, <span class="ruby-identifier">data</span>)
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-persistent_session_id-21" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">persistent_session_id!</span><span
            class="method-args">(data, sid = nil)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="persistent_session_id-21-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 149</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">persistent_session_id!</span>(<span class="ruby-identifier">data</span>, <span class="ruby-identifier">sid</span> = <span class="ruby-keyword">nil</span>)
  <span class="ruby-identifier">data</span> <span class="ruby-operator">||=</span> {}
  <span class="ruby-identifier">data</span>[<span class="ruby-string">&quot;session_id&quot;</span>] <span class="ruby-operator">||=</span> <span class="ruby-identifier">sid</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">generate_sid</span>
  <span class="ruby-identifier">data</span>
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-secure-3F" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">secure?</span><span
            class="method-args">(options)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="secure-3F-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 196</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">secure?</span>(<span class="ruby-identifier">options</span>)
  <span class="ruby-ivar">@secrets</span>.<span class="ruby-identifier">size</span> <span class="ruby-operator">&gt;=</span> <span class="ruby-value">1</span> <span class="ruby-operator">||</span>
  (<span class="ruby-identifier">options</span>[<span class="ruby-value">:coder</span>] <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-identifier">options</span>[<span class="ruby-value">:let_coder_handle_secure_encoding</span>])
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-unpacked_cookie_data" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">unpacked_cookie_data</span><span
            class="method-args">(request)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="unpacked_cookie_data-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 136</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">unpacked_cookie_data</span>(<span class="ruby-identifier">request</span>)
  <span class="ruby-identifier">request</span>.<span class="ruby-identifier">fetch_header</span>(<span class="ruby-constant">RACK_SESSION_UNPACKED_COOKIE_DATA</span>) <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">k</span><span class="ruby-operator">|</span>
    <span class="ruby-identifier">session_data</span> = <span class="ruby-identifier">request</span>.<span class="ruby-identifier">cookies</span>[<span class="ruby-ivar">@key</span>]

    <span class="ruby-keyword">if</span> <span class="ruby-ivar">@secrets</span>.<span class="ruby-identifier">size</span> <span class="ruby-operator">&gt;</span> <span class="ruby-value">0</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-identifier">session_data</span>
      <span class="ruby-identifier">session_data</span>, <span class="ruby-identifier">_</span>, <span class="ruby-identifier">digest</span> = <span class="ruby-identifier">session_data</span>.<span class="ruby-identifier">rpartition</span>(<span class="ruby-string">&#39;--&#39;</span>)
      <span class="ruby-identifier">session_data</span> = <span class="ruby-keyword">nil</span> <span class="ruby-keyword">unless</span> <span class="ruby-identifier">digest_match?</span>(<span class="ruby-identifier">session_data</span>, <span class="ruby-identifier">digest</span>)
    <span class="ruby-keyword">end</span>

    <span class="ruby-identifier">request</span>.<span class="ruby-identifier">set_header</span>(<span class="ruby-identifier">k</span>, <span class="ruby-identifier">coder</span>.<span class="ruby-identifier">decode</span>(<span class="ruby-identifier">session_data</span>) <span class="ruby-operator">||</span> {})
  <span class="ruby-keyword">end</span>
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
      <div id="method-i-write_session" class="method-detail ">
        
        <div class="method-heading">
          <span class="method-name">write_session</span><span
            class="method-args">(req, session_id, session, options)</span>
          
          <span class="method-click-advice">click to toggle source</span>
          
        </div>
        

        <div class="method-description">
          
          
          
          

          
          <div class="method-source-code" id="write_session-source">
            <pre><span class="ruby-comment"># File lib/rack/session/cookie.rb, line 164</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier ruby-title">write_session</span>(<span class="ruby-identifier">req</span>, <span class="ruby-identifier">session_id</span>, <span class="ruby-identifier">session</span>, <span class="ruby-identifier">options</span>)
  <span class="ruby-identifier">session</span> = <span class="ruby-identifier">session</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-string">&quot;session_id&quot;</span> <span class="ruby-operator">=&gt;</span> <span class="ruby-identifier">session_id</span>)
  <span class="ruby-identifier">session_data</span> = <span class="ruby-identifier">coder</span>.<span class="ruby-identifier">encode</span>(<span class="ruby-identifier">session</span>)

  <span class="ruby-keyword">if</span> <span class="ruby-ivar">@secrets</span>.<span class="ruby-identifier">first</span>
    <span class="ruby-identifier">session_data</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-node">&quot;--#{generate_hmac(session_data, @secrets.first)}&quot;</span>
  <span class="ruby-keyword">end</span>

  <span class="ruby-keyword">if</span> <span class="ruby-identifier">session_data</span>.<span class="ruby-identifier">size</span> <span class="ruby-operator">&gt;</span> (<span class="ruby-value">4096</span> <span class="ruby-operator">-</span> <span class="ruby-ivar">@key</span>.<span class="ruby-identifier">size</span>)
    <span class="ruby-identifier">req</span>.<span class="ruby-identifier">get_header</span>(<span class="ruby-constant">RACK_ERRORS</span>).<span class="ruby-identifier">puts</span>(<span class="ruby-string">&quot;Warning! Rack::Session::Cookie data size exceeds 4K.&quot;</span>)
    <span class="ruby-keyword">nil</span>
  <span class="ruby-keyword">else</span>
    <span class="ruby-constant">SessionId</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">session_id</span>, <span class="ruby-identifier">session_data</span>)
  <span class="ruby-keyword">end</span>
<span class="ruby-keyword">end</span></pre>
          </div>
          
        </div>

        

        
      </div>

    
    </section>
  
  </section>

</main>


<footer id="validator-badges" role="contentinfo">
  <p><a href="https://validator.w3.org/check/referer">Validate</a>
  <p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> 6.2.1.1.
  <p>Based on <a href="http://deveiate.org/projects/Darkfish-RDoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
</footer>



Current_dir [ NOT WRITEABLE ] Document_root [ WRITEABLE ]


[ Back ]
NAME
SIZE
LAST TOUCH
USER
CAN-I?
FUNCTIONS
..
--
14 Mar 2026 8.32 AM
root / root
0755
Abstract
--
14 Mar 2026 8.32 AM
root / root
0755
Cookie
--
14 Mar 2026 8.32 AM
root / root
0755
Abstract.html
2.471 KB
20 Feb 2026 12.28 PM
root / root
0644
Cookie.html
24.649 KB
20 Feb 2026 12.28 PM
root / root
0644
Pool.html
17.227 KB
20 Feb 2026 12.28 PM
root / root
0644
SessionId.html
9.472 KB
20 Feb 2026 12.28 PM
root / root
0644

GRAYBYTE WORDPRESS FILE MANAGER @ 2025 CONTACT ME
Static GIF