Overview

Namespaces

  • Peach
    • DF
    • DT
    • Http
      • Body
      • Header
    • Markup
    • Util

Classes

  • Peach\DF\Base64Codec
  • Peach\DF\CodecChain
  • Peach\DF\JsonCodec
  • Peach\DF\SerializationCodec
  • Peach\DF\Utf8Codec
  • Peach\DT\AbstractTime
  • Peach\DT\Clock
  • Peach\DT\Date
  • Peach\DT\Datetime
  • Peach\DT\DefaultClock
  • Peach\DT\FixedClock
  • Peach\DT\FormatWrapper
  • Peach\DT\HttpDateFormat
  • Peach\DT\OffsetClock
  • Peach\DT\ShiftFormat
  • Peach\DT\SimpleFormat
  • Peach\DT\TimeEquator
  • Peach\DT\Timestamp
  • Peach\DT\TimeWrapper
  • Peach\DT\UnixTimeFormat
  • Peach\DT\Util
  • Peach\DT\W3cDatetimeFormat
  • Peach\Http\Body
  • Peach\Http\Body\CodecRenderer
  • Peach\Http\Body\StringRenderer
  • Peach\Http\DefaultEndpoint
  • Peach\Http\Header\CookieItem
  • Peach\Http\Header\CookieOptions
  • Peach\Http\Header\HttpDate
  • Peach\Http\Header\NoField
  • Peach\Http\Header\QualityValues
  • Peach\Http\Header\Raw
  • Peach\Http\Header\SetCookie
  • Peach\Http\Header\Status
  • Peach\Http\Request
  • Peach\Http\Response
  • Peach\Http\Util
  • Peach\Markup\AbstractHelper
  • Peach\Markup\AbstractRenderer
  • Peach\Markup\BaseHelper
  • Peach\Markup\BreakControlWrapper
  • Peach\Markup\Builder
  • Peach\Markup\Code
  • Peach\Markup\Comment
  • Peach\Markup\ContainerElement
  • Peach\Markup\Context
  • Peach\Markup\DebugBuilder
  • Peach\Markup\DebugContext
  • Peach\Markup\DefaultBreakControl
  • Peach\Markup\DefaultBuilder
  • Peach\Markup\DefaultContext
  • Peach\Markup\Element
  • Peach\Markup\EmptyElement
  • Peach\Markup\HelperObject
  • Peach\Markup\HtmlHelper
  • Peach\Markup\Indent
  • Peach\Markup\MinimalBreakControl
  • Peach\Markup\NameBreakControl
  • Peach\Markup\NameValidator
  • Peach\Markup\NodeList
  • Peach\Markup\None
  • Peach\Markup\SgmlRenderer
  • Peach\Markup\Text
  • Peach\Markup\XmlRenderer
  • Peach\Util\AbstractMapEntry
  • Peach\Util\ArrayMap
  • Peach\Util\ArrayMapEntry
  • Peach\Util\Arrays
  • Peach\Util\DefaultComparator
  • Peach\Util\DefaultEquator
  • Peach\Util\HashMap
  • Peach\Util\HashMapEntry
  • Peach\Util\Strings
  • Peach\Util\Values

Interfaces

  • Peach\DF\Codec
  • Peach\DT\Format
  • Peach\DT\Time
  • Peach\Http\BodyRenderer
  • Peach\Http\Endpoint
  • Peach\Http\HeaderField
  • Peach\Http\MultiHeaderField
  • Peach\Http\SingleHeaderField
  • Peach\Markup\BreakControl
  • Peach\Markup\Component
  • Peach\Markup\Container
  • Peach\Markup\Helper
  • Peach\Markup\Node
  • Peach\Markup\Renderer
  • Peach\Util\Comparable
  • Peach\Util\Comparator
  • Peach\Util\Equator
  • Peach\Util\Map
  • Peach\Util\MapEntry
  • Overview
  • Namespace
  • Class
  1: <?php
  2: /*
  3:  * Copyright (c) 2016 @trashtoy
  4:  * https://github.com/trashtoy/
  5:  * 
  6:  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  7:  * this software and associated documentation files (the "Software"), to deal in
  8:  * the Software without restriction, including without limitation the rights to use,
  9:  * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
 10:  * Software, and to permit persons to whom the Software is furnished to do so,
 11:  * subject to the following conditions:
 12:  * 
 13:  * The above copyright notice and this permission notice shall be included in all
 14:  * copies or substantial portions of the Software.
 15:  * 
 16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 18:  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 19:  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 20:  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 21:  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22:  */
 23: /**
 24:  * PHP class file.
 25:  * @auhtor trashtoy
 26:  * @since  2.2.0
 27:  */
 28: namespace Peach\Http\Header;
 29: 
 30: use InvalidArgumentException;
 31: use Peach\DT\Timestamp;
 32: use Peach\DT\Util;
 33: use Peach\Util\Values;
 34: 
 35: /**
 36:  * Set-Cookie ヘッダーの各種属性をあらわすクラスです.
 37:  * このクラスのオブジェクトに対する変更は, 関連するすべての CookieItem オブジェクトに影響を与えます.
 38:  */
 39: class CookieOptions
 40: {
 41:     /**
 42:      * expires 属性の時刻をあらわす Timestamp オブジェクトです.
 43:      * 
 44:      * @var Timestamp
 45:      */
 46:     private $expires;
 47:     
 48:     /**
 49:      * このプログラムが扱う時刻のタイムゾーンです.
 50:      * この値が null の場合はデフォルトのタイムゾーンを適用します.
 51:      * 
 52:      * @var int
 53:      */
 54:     private $timeZoneOffset;
 55:     
 56:     /**
 57:      * max-age 属性をあらわす整数です.
 58:      * @var int
 59:      */
 60:     private $maxAge;
 61:     
 62:     /**
 63:      * domain 属性をあらわす文字列です.
 64:      * 
 65:      * @var string
 66:      */
 67:     private $domain;
 68:     
 69:     /**
 70:      * path 属性をあらわす文字列です.
 71:      * 
 72:      * @var string
 73:      */
 74:     private $path;
 75:     
 76:     /**
 77:      * secure 属性をあらわす論理値です.
 78:      * true の場合のみ secure 属性が付与されます.
 79:      * 
 80:      * @var bool
 81:      */
 82:     private $secure;
 83:     
 84:     /**
 85:      * 属性を何も持たない, 新しい CookieOptions オブジェクトを構築します.
 86:      */
 87:     public function __construct()
 88:     {
 89:         $this->secure = false;
 90:         $this->httpOnly = false;
 91:     }
 92:     
 93:     /**
 94:      * expires 属性の時刻を設定します.
 95:      * 引数に null を設定した場合は expires 属性を削除します.
 96:      * 
 97:      * @param Timestamp $expires Set-Cookie の expires 属性として表現される時刻
 98:      */
 99:     public function setExpires(Timestamp $expires = null)
100:     {
101:         $this->expires = $expires;
102:     }
103:     
104:     /**
105:      * expires 属性の時刻を返します.
106:      * expires 属性が設定されていない場合は null を返します.
107:      * 
108:      * @return Timestamp expires 属性の時刻
109:      */
110:     public function getExpires()
111:     {
112:         return $this->expires;
113:     }
114:     
115:     /**
116:      * このオブジェクトが取り扱う Timestamp オブジェクトの時差を分単位でセットします.
117:      * このメソッドは expires 属性の出力に影響します.
118:      * PHP の date.timezone 設定がシステムの時差と異なる場合に使用してください.
119:      * 通常はこのメソッドを使用する必要はありません.
120:      * 
121:      * もしも引数に -23:45 (1425) 以上または +23:45 (-1425) 未満の値を指定した場合は
122:      * -23:45 または +23:45 に丸めた結果を返します.
123:      * 
124:      * @param int $offset 時差
125:      * @see   Util::cleanTimeZoneOffset()
126:      */
127:     public function setTimeZoneOffset($offset)
128:     {
129:         $this->timeZoneOffset = ($offset === null) ? null : Util::cleanTimeZoneOffset($offset);
130:     }
131:     
132:     /**
133:      * このオブジェクトが取り扱う Timestamp オブジェクトの時差を返します.
134:      * このメソッドはデフォルトで null を返します.
135:      * 
136:      * @return int 時差. ただしデフォルトの場合は null
137:      */
138:     public function getTimeZoneOffset()
139:     {
140:         return $this->timeZoneOffset;
141:     }
142:     
143:     /**
144:      * max-age 属性の値をセットします.
145:      * 引数に 0 をセットした場合は対象の Cookie がブラウザから削除されます.
146:      * 引数が 0 未満の値の場合は 0 として扱われます.
147:      * 
148:      * @param int $maxAge max-age 属性の値
149:      */
150:     public function setMaxAge($maxAge)
151:     {
152:         $this->maxAge = ($maxAge === null) ? null : Values::intValue($maxAge, 0);
153:     }
154:     
155:     /**
156:      * max-age 属性の値を返します.
157:      * もしも max-age 属性がセットされていない場合は null を返します.
158:      * 
159:      * @return int max-age 属性の値. セットされていない場合は null
160:      */
161:     public function getMaxAge()
162:     {
163:         return $this->maxAge;
164:     }
165:     
166:     /**
167:      * domain 属性の値をセットします.
168:      * 引数に null をセットした場合は domain 属性を削除します.
169:      * 
170:      * @param string $domain domain 属性の値
171:      */
172:     public function setDomain($domain)
173:     {
174:         if (!$this->validateDomain($domain)) {
175:             throw new InvalidArgumentException("Invalid domain: '{$domain}'");
176:         }
177:         $this->domain = $domain;
178:     }
179:     
180:     /**
181:      * 指定された文字列が, ドメイン名として妥当かどうかを確認します.
182:      * RFC 1035 に基づいて, 引数の文字列が以下の BNF 記法を満たすかどうかを調べます.
183:      * 妥当な場合は true, そうでない場合は false を返します.
184:      * 
185:      * ただし, 本来は Invalid にも関わらず実際に使われているドメイン名に対応するため
186:      * label の先頭の数字文字列を敢えて許す実装となっています.
187:      * 
188:      * <pre>
189:      * {domain} ::= {subdomain} | " "
190:      * {subdomain} ::= {label} | {subdomain} "." {label}
191:      * {label} ::= {letter} [ [ {ldh-str} ] {let-dig} ]
192:      * {ldh-str} ::= {let-dig-hyp} | {let-dig-hyp} {ldh-str}
193:      * {let-dig-hyp} ::= {let-dig} | "-"
194:      * {let-dig} ::= {letter} | {digit}
195:      * </pre>
196:      * 
197:      * @param  string $domain 検査対象のドメイン名
198:      * @return bool           引数がドメイン名として妥当な場合のみ true
199:      */
200:     private function validateDomain($domain)
201:     {
202:         if ($domain === null) {
203:             return true;
204:         }
205:         $letter    = "[a-zA-Z0-9]";
206:         $letDigHyp = "(-|{$letter})";
207:         $label     = "{$letter}({$letDigHyp}*{$letter})*";
208:         $pattern   = "{$label}(\\.{$label})*";
209:         return preg_match("/\\A{$pattern}\\z/", $domain);
210:     }
211:     
212:     /**
213:      * domain 属性の値を返します.
214:      * domain 属性がセットされていない場合は null を返します.
215:      * 
216:      * @return string
217:      */
218:     public function getDomain()
219:     {
220:         return $this->domain;
221:     }
222:     
223:     /**
224:      * path 属性の値をセットします.
225:      * 引数に null をセットした場合は path 属性を削除します.
226:      * 
227:      * @param string $path
228:      */
229:     public function setPath($path)
230:     {
231:         if (!$this->validatePath($path)) {
232:             throw new InvalidArgumentException("Invalid path: '{$path}'");
233:         }
234:         $this->path = $path;
235:     }
236:     
237:     /**
238:      * 指定された文字列が RFC 3986 にて定義される URI のパス文字列として妥当かどうかを検証します.
239:      * フォーマットは以下の BNF 記法に基づきます.
240:      * 
241:      * <pre>
242:      * path-absolute = "/" [ segment-nz *( "/" segment ) ]
243:      * segment       = *pchar
244:      * segment-nz    = 1*pchar
245:      * pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
246:      * unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
247:      * pct-encoded   = "%" HEXDIG HEXDIG
248:      * sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
249:      * </pre>
250:      * 
251:      * @param  string $path 検査対象のパス
252:      * @return bool         引数がパスとして妥当な場合のみ true
253:      */
254:     private function validatePath($path)
255:     {
256:         if ($path === null) {
257:             return true;
258:         }
259:         
260:         $classUnreserved = "a-zA-Z0-9\\-\\._~";
261:         $classSubDelims  = "!\$&'\\(\\)";
262:         $classOthers     = ":@";
263:         $validChars      = "[{$classUnreserved}{$classSubDelims}{$classOthers}]";
264:         $pctEncoded      = "%[0-9a-fA-F]{2}";
265:         $pchar           = "{$validChars}|{$pctEncoded}";
266:         $segment         = "({$pchar})*";
267:         $segmentNz       = "({$pchar})+";
268:         $pathAbsolute    = "\\/({$segmentNz}(\\/{$segment})*)?";
269:         return preg_match("/\\A{$pathAbsolute}\\z/", $path);
270:     }
271:     
272:     /**
273:      * path 属性の値を返します.
274:      * もしも path 属性がセットされていない場合は null を返します.
275:      * 
276:      * @return string path 属性の値. セットされていない場合は null
277:      */
278:     public function getPath()
279:     {
280:         return $this->path;
281:     }
282:     
283:     /**
284:      * secure 属性をセットします.
285:      * もしも引数が true の場合は secure 属性を有効化, false の場合は無効化します.
286:      * 
287:      * @param bool $secure secure 属性を有効化する場合は true, 無効化する場合は false
288:      */
289:     public function setSecure($secure)
290:     {
291:         $this->secure = (bool) $secure;
292:     }
293:     
294:     /**
295:      * secure 属性が有効かどうかを判定します.
296:      * secure 属性が有効な場合は true, そうでない場合は false を返します.
297:      * もしもこのオブジェクトの setSecure() を一度も実行していない場合,
298:      * secure 属性は無効となるため false を返します.
299:      * 
300:      * @return bool secure 属性が有効な場合は true, そうでない場合は false
301:      */
302:     public function hasSecure()
303:     {
304:         return $this->secure;
305:     }
306:     
307:     /**
308:      * httponly 属性をセットします.
309:      * もしも引数が true の場合は httponly 属性を有効化, false の場合は無効化します.
310:      * 
311:      * @param bool $httpOnly httponly 属性を有効化する場合は true, 無効化する場合は false
312:      */
313:     public function setHttpOnly($httpOnly)
314:     {
315:         $this->httpOnly = (bool) $httpOnly;
316:     }
317:     
318:     /**
319:      * httponly 属性が有効かどうかを判定します.
320:      * httponly 属性が有効な場合は true, そうでない場合は false を返します.
321:      * もしもこのオブジェクトの setHttpOnly() を一度も実行していない場合,
322:      * httponly 属性は無効となるため false を返します.
323:      * 
324:      * @return bool httponly 属性が有効な場合は true, そうでない場合は false
325:      */
326:     public function hasHttpOnly()
327:     {
328:         return $this->httpOnly;
329:     }
330:     
331:     /**
332:      * このオブジェクトが持つ各属性を書式化し, 結果を配列で返します.
333:      * 
334:      * @return array 各属性を書式化した結果の配列
335:      * @ignore
336:      * @todo 複数の Set-Cookie ヘッダーで同じオプションを適用することを想定し, 返り値をキャッシュできるようにする
337:      */
338:     public function formatOptions()
339:     {
340:         $result = array();
341:         if ($this->expires !== null) {
342:             $result[] = $this->formatExpires();
343:         }
344:         if ($this->maxAge !== null) {
345:             $result[] = "max-age={$this->maxAge}";
346:         }
347:         if ($this->domain !== null) {
348:             $result[] = "domain={$this->domain}";
349:         }
350:         if ($this->path !== null) {
351:             $result[] = "path={$this->path}";
352:         }
353:         if ($this->secure) {
354:             $result[] = "secure";
355:         }
356:         if ($this->httpOnly) {
357:             $result[] = "httponly";
358:         }
359:         return $result;
360:     }
361:     
362:     /**
363:      * expires 属性を書式化します.
364:      * 
365:      * @return string "expires=Wdy, DD-Mon-YY HH:MM:SS GMT" 形式の文字列
366:      */
367:     private function formatExpires()
368:     {
369:         $format = CookieExpiresFormat::getInstance();
370:         $offset = Util::cleanTimeZoneOffset($this->timeZoneOffset);
371:         $date   = $format->format($this->expires, $offset);
372:         return "expires={$date}";
373:     }
374: }
375: 
PEACH2 API documentation generated by ApiGen