http://www.tutorialspoint.com/http/http_methods.htm 에서 참조

The HEAD Method

A HEAD request is just like a GET request, except it asks the server to return the response headers only, and not the actual resource (i.e. no message body). This is useful to check characteristics of a resource without actually downloading it, thus saving bandwidth. Use HEAD when you don’t actually need a file’s contents.

The response to a HEAD request must never contain a message body, just the status line and headers.

Strings

A string is series of characters, where a character is the same as a byte. This means that PHP only supports a 256-character set, and hence does not offer native Unicode support. See details of the string type.

Note: string can be as large as 2GB.

Syntax

A string literal can be specified in four different ways:

Single quoted

The simplest way to specify a string is to enclose it in single quotes (the character ).

To specify a literal single quote, escape it with a backslash (). To specify a literal backslash, double it (). All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as r or n, will be output literally as specified rather than having any special meaning.

Note: Unlike the double-quoted and heredoc syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings.

<?php
echo 'this is a simple string';

echo 'You can also have embedded newlines in 
strings this way as it is
okay to do';

// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I'll be back"';

// Outputs: You deleted C:*.*?
echo 'You deleted C:\*.*?';

// Outputs: You deleted C:*.*?
echo 'You deleted C:*.*?';

// Outputs: This will not expand: n a newline
echo 'This will not expand: n a newline';

// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either';
?>

Double quoted

If the string is enclosed in double-quotes (“), PHP will interpret more escape sequences for special characters:

Escaped characters Sequence Meaning n linefeed (LF or 0x0A (10) in ASCII) r carriage return (CR or 0x0D (13) in ASCII) t horizontal tab (HT or 0x09 (9) in ASCII) v vertical tab (VT or 0x0B (11) in ASCII) (since PHP 5.2.5) e escape (ESC or 0x1B (27) in ASCII) (since PHP 5.4.0) f form feed (FF or 0x0C (12) in ASCII) (since PHP 5.2.5) backslash $ dollar sign double-quote [0-7]{1,3} the sequence of characters matching the regular expression is a character in octal notation x[0-9A-Fa-f]{1,2}the sequence of characters matching the regular expression is a character in hexadecimal notation

As in single quoted strings, escaping any other character will result in the backslash being printed too. Before PHP 5.1.1, the backslash in {$var} had not been printed.

The most important feature of double-quoted strings is the fact that variable names will be expanded. See string parsing for details.

Heredoc

A third way to delimit strings is the heredoc syntax: <<<. After this operator, an identifier is provided, then a newline. The string itself follows, and then the same identifier again to close the quotation.

The closing identifier must begin in the first column of the line. Also, the identifier must follow the same naming rules as any other label in PHP: it must contain only alphanumeric characters and underscores, and must start with a non-digit character or underscore.

Warning

It is very important to note that the line with the closing identifier must contain no other characters, except possibly a semicolon (;). That means especially that the identifier may not be indented, and there may not be any spaces or tabs before or after the semicolon. It’s also important to realize that the first character before the closing identifier must be a newline as defined by the local operating system. This is n on UNIX systems, including Mac OS X. The closing delimiter (possibly followed by a semicolon) must also be followed by a newline.

If this rule is broken and the closing identifier is not "clean”, it will not be considered a closing identifier, and PHP will continue looking for one. If a proper closing identifier is not found before the end of the current file, a parse error will result at the last line.

Heredocs can not be used for initializing class properties. Since PHP 5.3, this limitation is valid only for heredocs containing variables.

Example #1 Invalid example

<?php
class foo {
    public $bar = <<<EOT
bar
    EOT;
}
?>

Heredoc text behaves just like a double-quoted string, without the double quotes. This means that quotes in a heredoc do not need to be escaped, but the escape codes listed above can still be used. Variables are expanded, but the same care must be taken when expressing complex variables inside a heredoc as with strings.

Example #2 Heredoc string quoting example

<?php
$str 
= <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    var $foo;
    var $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'MyName';

echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': x41
EOT;
?>

The above example will output:

My name is "MyName". I am printing some Foo.
Now, I am printing some Bar2.
This should print a capital 'A': A

It is also possible to use the Heredoc syntax to pass data to function arguments:

Example #3 Heredoc in arguments example

<?php
var_dump
(array(<<<EOD
foobar!
EOD
));
?>

As of PHP 5.3.0, it’s possible to initialize static variables and class properties/constants using the Heredoc syntax:

Example #4 Using Heredoc to initialize static values

<?php
// Static variables
function foo()
{
    static $bar = <<<LABEL
Nothing in here...
LABEL;
}

// Class properties/constants
class foo
{
    const BAR = <<<FOOBAR
Constant example
FOOBAR;

    public $baz = <<<FOOBAR
Property example
FOOBAR;
}
?>

Starting with PHP 5.3.0, the opening Heredoc identifier may optionally be enclosed in double quotes:

Example #5 Using double quotes in Heredoc

<?php
echo <<<"FOOBAR"
Hello World!
FOOBAR;
?>

Nowdoc

Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no parsing is done inside a nowdoc. The construct is ideal for embedding PHP code or other large blocks of text without the need for escaping. It shares some features in common with the SGML <![CDATA[ ]]> construct, in that it declares a block of text which is not for parsing.

A nowdoc is identified with the same <<< sequence used for heredocs, but the identifier which follows is enclosed in single quotes, e.g. <<<‘EOT’. All the rules for heredoc identifiers also apply to nowdoc identifiers, especially those regarding the appearance of the closing identifier.

Example #6 Nowdoc string quoting example

<?php
$str 
= <<<'EOD'
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    public $foo;
    public $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'MyName';

echo <<<'EOT'
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': x41
EOT;
?>

The above example will output:

My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': x41

Note:

Unlike heredocs, nowdocs can be used in any static data context. The typical example is initializing class properties or constants:

Example #7 Static data example

<?php
class foo {
    public $bar = <<<'EOT'
bar
EOT;
}
?>

Note:

Nowdoc support was added in PHP 5.3.0.

Variable parsing

When a string is specified in double quotes or with heredoc, variables are parsed within it.

There are two types of syntax: a simple one and a complex one. The simple syntax is the most common and convenient. It provides a way to embed a variable, an array value, or an object property in a string with a minimum of effort.

The complex syntax can be recognised by the curly braces surrounding the expression.

Simple syntax

If a dollar sign ($) is encountered, the parser will greedily take as many tokens as possible to form a valid variable name. Enclose the variable name in curly braces to explicitly specify the end of the name.

<?php
$juice 
= "apple";

echo "He drank some $juice juice.".PHP_EOL;
// Invalid. "s" is a valid character for a variable name, but the variable is $juice.
echo "He drank some juice made of $juices.";
?>

The above example will output:

He drank some apple juice.
He drank some juice made of .

Similarly, an array index or an object property can be parsed. With array indices, the closing square bracket (]) marks the end of the index. The same rules apply to object properties as to simple variables.

Example #8 Simple syntax example

<?php
$juices 
= array("apple", "orange", "koolaid1" => "purple");

echo "He drank some $juices[0] juice.".PHP_EOL;
echo "He drank some $juices[1] juice.".PHP_EOL;
echo "He drank some juice made of $juice[0]s.".PHP_EOL; // Won't work
echo "He drank some $juices[koolaid1] juice.".PHP_EOL;

class people {
    public $john = "John Smith";
    public $jane = "Jane Smith";
    public $robert = "Robert Paulsen";
    
    public $smith = "Smith";
}

$people = new people();

echo "$people->john drank some $juices[0] juice.".PHP_EOL;
echo "$people->john then said hello to $people->jane.".PHP_EOL;
echo "$people->john's wife greeted $people->robert.".PHP_EOL;
echo "$people->robert greeted the two $people->smiths."; // Won't work
?>

The above example will output:

He drank some apple juice.
He drank some orange juice.
He drank some juice made of s.
He drank some purple juice.
John Smith drank some apple juice.
John Smith then said hello to Jane Smith.
John Smith's wife greeted Robert Paulsen.
Robert Paulsen greeted the two .

For anything more complex, you should use the complex syntax.

Complex (curly) syntax

This isn’t called complex because the syntax is complex, but because it allows for the use of complex expressions.

Any scalar variable, array element or object property with a string representation can be included via this syntax. Simply write the expression the same way as it would appear outside the string, and then wrap it in { and }. Since { can not be escaped, this syntax will only be recognised when the $ immediately follows the {. Use {$ to get a literal {$. Some examples to make it clear:

<?php
// Show all errors
error_reporting(E_ALL);

$great = 'fantastic';

// Won't work, outputs: This is { fantastic}
echo "This is { $great}";

// Works, outputs: This is fantastic
echo "This is {$great}";
echo "This is ${great}";

// Works
echo "This square is {$square->width}00 centimeters broad."; 

// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";

// Works
echo "This works: {$arr[4][3]}";

// This is wrong for the same reason as $foo[bar] is wrong  outside a string.
// In other words, it will still work, but only because PHP first looks for a
// constant named foo; an error of level E_NOTICE (undefined constant) will be
// thrown.
echo "This is wrong: {$arr[foo][3]}"; 

// Works. When using multi-dimensional arrays, always use braces around arrays
// when inside of strings
echo "This works: {$arr['foo'][3]}";

// Works.
echo "This works: " . $arr['foo'][3];

echo "This works too: {$obj->values[3]->name}";

echo "This is the value of the var named $name: {${$name}}";

echo "This is the value of the var named by the return value of getName(): {${getName()}}";

echo "This is the value of the var named by the return value of $object->getName(): {${$object->getName()}}";

// Won't work, outputs: This is the return value of getName(): {getName()}
echo "This is the return value of getName(): {getName()}";
?>

It is also possible to access class properties using variables within strings using this syntax.

<?php
class foo {
    var $bar = 'I am bar.';
}

$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}n";
echo "{$foo->$baz[1]}n";
?>

The above example will output:

I am bar.
I am bar.

Note:

Functions, method calls, static class variables, and class constants inside {$} work since PHP 5. However, the value accessed will be interpreted as the name of a variable in the scope in which the string is defined. Using single curly braces ({}) will not work for accessing the return values of functions or methods or the values of class constants or static class variables.

<?php
// Show all errors.
error_reporting(E_ALL);

class beers {
    const softdrink = 'rootbeer';
    public static $ale = 'ipa';
}

$rootbeer = 'A & W';
$ipa = 'Alexander Keith's';

// This works; outputs: I'd like an A & W
echo "I'd like an {${beers::softdrink}}n";

// This works too; outputs: I'd like an Alexander Keith's
echo "I'd like an {${beers::$ale}}n";
?>

String access and modification by character

Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string using square array brackets, as in $str[42]. Think of a string as an array of characters for this purpose. The functions substr() and substr_replace() can be used when you want to extract or replace more than 1 character.

Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.

Warning

Writing to an out of range offset pads the string with spaces. Non-integer types are converted to integer. Illegal offset type emits E_NOTICE. Negative offset emits E_NOTICE in write but reads empty string. Only the first character of an assigned string is used. Assigning empty string assigns NULL byte.

Warning

Internally, PHP strings are byte arrays. As a result, accessing or modifying a string using array brackets is not multi-byte safe, and should only be done with strings that are in a single-byte encoding such as ISO-8859-1.

Example #9 Some string examples

<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str[0];

// Get the third character of a string
$third = $str[2];

// Get the last character of a string.
$str = 'This is still a test.';
$last = $str[strlen($str)-1]; 

// Modify the last character of a string
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';

?>

As of PHP 5.4 string offsets have to either be integers or integer-like strings, otherwise a warning will be thrown. Previously an offset like “foo” was silently cast to 0.

Example #10 Differences between PHP 5.3 and PHP 5.4

<?php
$str 
= 'abc';

var_dump($str['1']);
var_dump(isset($str['1']));

var_dump($str['1.0']);
var_dump(isset($str['1.0']));

var_dump($str['x']);
var_dump(isset($str['x']));

var_dump($str['1x']);
var_dump(isset($str['1x']));
?>

Output of the above example in PHP 5.3:

string(1) "b"
bool(true)
string(1) "b"
bool(true)
string(1) "a"
bool(true)
string(1) "b"
bool(true)

Output of the above example in PHP 5.4:

string(1) "b"
bool(true)

Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
string(1) "b"
bool(false)

Warning: Illegal string offset 'x' in /tmp/t.php on line 9
string(1) "a"
bool(false)
string(1) "b"
bool(false)

Note:

Accessing variables of other types (not including arrays or objects implementing the appropriate interfaces) using [] or {} silently returns NULL.

Note:

PHP 5.5 added support for accessing characters within string literals using [] or {}.

Useful functions and operators

Strings may be concatenated using the ’.’ (dot) operator. Note that the ’+’ (addition) operator will not work for this. See String operators for more information.

There are a number of useful functions for string manipulation.

See the string functions section for general functions, and the regular expression functions or the Perl-compatible regular expression functions for advanced find & replace functionality.

There are also functions for URL strings, and functions to encrypt/decrypt strings (mcrypt and mhash).

Finally, see also the character type functions.

Converting to string

A value can be converted to a string using the (string) cast or the strval() function. String conversion is automatically done in the scope of an expression where a string is needed. This happens when using the echo or print functions, or when a variable is compared to a string. The sections on Types and Type Juggling will make the following clearer. See also the settype() function.

A boolean TRUE value is converted to the string “1”. Boolean FALSE is converted to “” (the empty string). This allows conversion back and forth between boolean and string values.

An integer or float is converted to a string representing the number textually (including the exponent part for floats). Floating point numbers can be converted using exponential notation (4.1E+6).

Note:

The decimal point character is defined in the script’s locale (category LC_NUMERIC). See the setlocale() function.

Arrays are always converted to the string “Array”; because of this, echo and print can not by themselves show the contents of an array. To view a single element, use a construction such as echo $arr[‘foo’]. See below for tips on viewing the entire contents.

Objects in PHP 4 are always converted to the string “Object”. To print the values of object properties for debugging reasons, read the paragraphs below. To get an object’s class name, use the get_class() function. As of PHP 5, the __toString method is used when applicable.

Resources are always converted to strings with the structure “Resource id #1”, where 1 is the unique number assigned to the resource by PHP at runtime. Do not rely upon this structure; it is subject to change. To get a resource’s type, use the get_resource_type() function.

NULL is always converted to an empty string.

As stated above, directly converting an array, object, or resource to a string does not provide any useful information about the value beyond its type. See the functions print_r() and var_dump() for more effective means of inspecting the contents of these types.

Most PHP values can also be converted to strings for permanent storage. This method is called serialization, and is performed by the serialize() function. If the PHP engine was built with WDDX support, PHP values can also be serialized as well-formed XML text.

String conversion to numbers

When a string is evaluated in a numeric context, the resulting value and type are determined as follows.

If the string does not contain any of the characters ’.’, ‘e’, or ‘E’ and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.

The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an ‘e’ or ‘E’ followed by one or more digits.

<?php
$foo 
= 1 + "10.5";                // $foo is float (11.5)
$foo = 1 + "-1.3e3";              // $foo is float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo is integer (1)
$foo = 1 + "bob3";                // $foo is integer (1)
$foo = 1 + "10 Small Pigs";       // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1;          // $foo is float (11)
$foo = "10.0 pigs " + 1.0;        // $foo is float (11)     
?>

For more information on this conversion, see the Unix manual page for strtod(3).

To test any of the examples in this section, cut and paste the examples and insert the following line to see what’s going on:

<?php
echo "$foo==$foo; type is " . gettype ($foo) . "<br />n";
?>

Do not expect to get the code of one character by converting it to integer, as is done in C. Use the ord() and chr() functions to convert between ASCII codes and characters.

Details of the String Type

The string in PHP is implemented as an array of bytes and an integer indicating the length of the buffer. It has no information about how those bytes translate to characters, leaving that task to the programmer. There are no limitations on the values the string can be composed of; in particular, bytes with value 0 (“NUL bytes”) are allowed anywhere in the string (however, a few functions, said in this manual not to be “binary safe”, may hand off the strings to libraries that ignore data after a NUL byte.)

This nature of the string type explains why there is no separate “byte” type in PHP – strings take this role. Functions that return no textual data – for instance, arbitrary data read from a network socket – will still return strings.

Given that PHP does not dictate a specific encoding for strings, one might wonder how string literals are encoded. For instance, is the string “á” equivalent to “xE1” (ISO-8859-1), “xC3xA1” (UTF-8, C form), “x61xCCx81” (UTF-8, D form) or any other possible representation? The answer is that string will be encoded in whatever fashion it is encoded in the script file. Thus, if the script is written in ISO-8859-1, the string will be encoded in ISO-8859-1 and so on. However, this does not apply if Zend Multibyte is enabled; in that case, the script may be written in an arbitrary encoding (which is explicity declared or is detected) and then converted to a certain internal encoding, which is then the encoding that will be used for the string literals. Note that there are some constraints on the encoding of the script (or on the internal encoding, should Zend Multibyte be enabled) – this almost always means that this encoding should be a compatible superset of ASCII, such as UTF-8 or ISO-8859-1. Note, however, that state-dependent encodings where the same byte values can be used in initial and non-initial shift states may be problematic.

Of course, in order to be useful, functions that operate on text may have to make some assumptions about how the string is encoded. Unfortunately, there is much variation on this matter throughout PHP’s functions:

  • Some functions assume that the string is encoded in some (any) single-byte encoding, but they do not need to interpret those bytes as specific characters. This is case of, for instance, substr(), strpos(), strlen() or strcmp(). Another way to think of these functions is that operate on memory buffers, i.e., they work with bytes and byte offsets.
  • Other functions are passed the encoding of the string, possibly they also assume a default if no such information is given. This is the case of htmlentities() and the majority of the functions in the mbstring extension.
  • Others use the current locale (see setlocale()), but operate byte-by-byte. This is the case of strcasecmp(), strtoupper() and ucfirst(). This means they can be used only with single-byte encodings, as long as the encoding is matched by the locale. For instance strtoupper(“á”) may return “Á” if the locale is correctly set and á is encoded with a single byte. If it is encoded in UTF-8, the correct result will not be returned and the resulting string may or may not be returned corrupted, depending on the current locale.
  • Finally, they may just assume the string is using a specific encoding, usually UTF-8. This is the case of most functions in the intl extension and in the PCRE extension (in the last case, only when the u modifier is used). Although this is due to their special purpose, the function utf8_decode() assumes a UTF-8 encoding and the function utf8_encode() assumes an ISO-8859-1 encoding.

Ultimately, this means writing correct programs using Unicode depends on carefully avoiding functions that will not work and that most likely will corrupt the data and using instead the functions that do behave correctly, generally from the intl and mbstring extensions. However, using functions that can handle Unicode encodings is just the beginning. No matter the functions the language provides, it is essential to know the Unicode specification. For instance, a program that assumes there is only uppercase and lowercase is making a wrong assumption.

Strings

A string is series of characters, where a character is the same as a byte. This means that PHP only supports a 256-character set, and hence does not offer native Unicode support. See details of the string type.

Note: string can be as large as 2GB.

Syntax

A string literal can be specified in four different ways:

Single quoted

The simplest way to specify a string is to enclose it in single quotes (the character ).

To specify a literal single quote, escape it with a backslash (). To specify a literal backslash, double it (). All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as r or n, will be output literally as specified rather than having any special meaning.

Note: Unlike the double-quoted and heredoc syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings.

<?php
echo 'this is a simple string';

echo 'You can also have embedded newlines in 
strings this way as it is
okay to do';

// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I'll be back"';

// Outputs: You deleted C:*.*?
echo 'You deleted C:\*.*?';

// Outputs: You deleted C:*.*?
echo 'You deleted C:*.*?';

// Outputs: This will not expand: n a newline
echo 'This will not expand: n a newline';

// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either';
?>

Double quoted

If the string is enclosed in double-quotes (“), PHP will interpret more escape sequences for special characters:

Escaped characters Sequence Meaning n linefeed (LF or 0x0A (10) in ASCII) r carriage return (CR or 0x0D (13) in ASCII) t horizontal tab (HT or 0x09 (9) in ASCII) v vertical tab (VT or 0x0B (11) in ASCII) (since PHP 5.2.5) e escape (ESC or 0x1B (27) in ASCII) (since PHP 5.4.0) f form feed (FF or 0x0C (12) in ASCII) (since PHP 5.2.5) backslash $ dollar sign double-quote [0-7]{1,3} the sequence of characters matching the regular expression is a character in octal notation x[0-9A-Fa-f]{1,2}the sequence of characters matching the regular expression is a character in hexadecimal notation

As in single quoted strings, escaping any other character will result in the backslash being printed too. Before PHP 5.1.1, the backslash in {$var} had not been printed.

The most important feature of double-quoted strings is the fact that variable names will be expanded. See string parsing for details.

Heredoc

A third way to delimit strings is the heredoc syntax: <<<. After this operator, an identifier is provided, then a newline. The string itself follows, and then the same identifier again to close the quotation.

The closing identifier must begin in the first column of the line. Also, the identifier must follow the same naming rules as any other label in PHP: it must contain only alphanumeric characters and underscores, and must start with a non-digit character or underscore.

Warning

It is very important to note that the line with the closing identifier must contain no other characters, except possibly a semicolon (;). That means especially that the identifier may not be indented, and there may not be any spaces or tabs before or after the semicolon. It’s also important to realize that the first character before the closing identifier must be a newline as defined by the local operating system. This is n on UNIX systems, including Mac OS X. The closing delimiter (possibly followed by a semicolon) must also be followed by a newline.

If this rule is broken and the closing identifier is not "clean”, it will not be considered a closing identifier, and PHP will continue looking for one. If a proper closing identifier is not found before the end of the current file, a parse error will result at the last line.

Heredocs can not be used for initializing class properties. Since PHP 5.3, this limitation is valid only for heredocs containing variables.

Example #1 Invalid example

<?php
class foo {
    public $bar = <<<EOT
bar
    EOT;
}
?>

Heredoc text behaves just like a double-quoted string, without the double quotes. This means that quotes in a heredoc do not need to be escaped, but the escape codes listed above can still be used. Variables are expanded, but the same care must be taken when expressing complex variables inside a heredoc as with strings.

Example #2 Heredoc string quoting example

<?php
$str 
= <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    var $foo;
    var $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'MyName';

echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': x41
EOT;
?>

The above example will output:

My name is "MyName". I am printing some Foo.
Now, I am printing some Bar2.
This should print a capital 'A': A

It is also possible to use the Heredoc syntax to pass data to function arguments:

Example #3 Heredoc in arguments example

<?php
var_dump
(array(<<<EOD
foobar!
EOD
));
?>

As of PHP 5.3.0, it’s possible to initialize static variables and class properties/constants using the Heredoc syntax:

Example #4 Using Heredoc to initialize static values

<?php
// Static variables
function foo()
{
    static $bar = <<<LABEL
Nothing in here...
LABEL;
}

// Class properties/constants
class foo
{
    const BAR = <<<FOOBAR
Constant example
FOOBAR;

    public $baz = <<<FOOBAR
Property example
FOOBAR;
}
?>

Starting with PHP 5.3.0, the opening Heredoc identifier may optionally be enclosed in double quotes:

Example #5 Using double quotes in Heredoc

<?php
echo <<<"FOOBAR"
Hello World!
FOOBAR;
?>

Nowdoc

Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no parsing is done inside a nowdoc. The construct is ideal for embedding PHP code or other large blocks of text without the need for escaping. It shares some features in common with the SGML <![CDATA[ ]]> construct, in that it declares a block of text which is not for parsing.

A nowdoc is identified with the same <<< sequence used for heredocs, but the identifier which follows is enclosed in single quotes, e.g. <<<‘EOT’. All the rules for heredoc identifiers also apply to nowdoc identifiers, especially those regarding the appearance of the closing identifier.

Example #6 Nowdoc string quoting example

<?php
$str 
= <<<'EOD'
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    public $foo;
    public $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'MyName';

echo <<<'EOT'
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': x41
EOT;
?>

The above example will output:

My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': x41

Note:

Unlike heredocs, nowdocs can be used in any static data context. The typical example is initializing class properties or constants:

Example #7 Static data example

<?php
class foo {
    public $bar = <<<'EOT'
bar
EOT;
}
?>

Note:

Nowdoc support was added in PHP 5.3.0.

Variable parsing

When a string is specified in double quotes or with heredoc, variables are parsed within it.

There are two types of syntax: a simple one and a complex one. The simple syntax is the most common and convenient. It provides a way to embed a variable, an array value, or an object property in a string with a minimum of effort.

The complex syntax can be recognised by the curly braces surrounding the expression.

Simple syntax

If a dollar sign ($) is encountered, the parser will greedily take as many tokens as possible to form a valid variable name. Enclose the variable name in curly braces to explicitly specify the end of the name.

<?php
$juice 
= "apple";

echo "He drank some $juice juice.".PHP_EOL;
// Invalid. "s" is a valid character for a variable name, but the variable is $juice.
echo "He drank some juice made of $juices.";
?>

The above example will output:

He drank some apple juice.
He drank some juice made of .

Similarly, an array index or an object property can be parsed. With array indices, the closing square bracket (]) marks the end of the index. The same rules apply to object properties as to simple variables.

Example #8 Simple syntax example

<?php
$juices 
= array("apple", "orange", "koolaid1" => "purple");

echo "He drank some $juices[0] juice.".PHP_EOL;
echo "He drank some $juices[1] juice.".PHP_EOL;
echo "He drank some juice made of $juice[0]s.".PHP_EOL; // Won't work
echo "He drank some $juices[koolaid1] juice.".PHP_EOL;

class people {
    public $john = "John Smith";
    public $jane = "Jane Smith";
    public $robert = "Robert Paulsen";
    
    public $smith = "Smith";
}

$people = new people();

echo "$people->john drank some $juices[0] juice.".PHP_EOL;
echo "$people->john then said hello to $people->jane.".PHP_EOL;
echo "$people->john's wife greeted $people->robert.".PHP_EOL;
echo "$people->robert greeted the two $people->smiths."; // Won't work
?>

The above example will output:

He drank some apple juice.
He drank some orange juice.
He drank some juice made of s.
He drank some purple juice.
John Smith drank some apple juice.
John Smith then said hello to Jane Smith.
John Smith's wife greeted Robert Paulsen.
Robert Paulsen greeted the two .

For anything more complex, you should use the complex syntax.

Complex (curly) syntax

This isn’t called complex because the syntax is complex, but because it allows for the use of complex expressions.

Any scalar variable, array element or object property with a string representation can be included via this syntax. Simply write the expression the same way as it would appear outside the string, and then wrap it in { and }. Since { can not be escaped, this syntax will only be recognised when the $ immediately follows the {. Use {$ to get a literal {$. Some examples to make it clear:

<?php
// Show all errors
error_reporting(E_ALL);

$great = 'fantastic';

// Won't work, outputs: This is { fantastic}
echo "This is { $great}";

// Works, outputs: This is fantastic
echo "This is {$great}";
echo "This is ${great}";

// Works
echo "This square is {$square->width}00 centimeters broad."; 

// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";

// Works
echo "This works: {$arr[4][3]}";

// This is wrong for the same reason as $foo[bar] is wrong  outside a string.
// In other words, it will still work, but only because PHP first looks for a
// constant named foo; an error of level E_NOTICE (undefined constant) will be
// thrown.
echo "This is wrong: {$arr[foo][3]}"; 

// Works. When using multi-dimensional arrays, always use braces around arrays
// when inside of strings
echo "This works: {$arr['foo'][3]}";

// Works.
echo "This works: " . $arr['foo'][3];

echo "This works too: {$obj->values[3]->name}";

echo "This is the value of the var named $name: {${$name}}";

echo "This is the value of the var named by the return value of getName(): {${getName()}}";

echo "This is the value of the var named by the return value of $object->getName(): {${$object->getName()}}";

// Won't work, outputs: This is the return value of getName(): {getName()}
echo "This is the return value of getName(): {getName()}";
?>

It is also possible to access class properties using variables within strings using this syntax.

<?php
class foo {
    var $bar = 'I am bar.';
}

$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo "{$foo->$bar}n";
echo "{$foo->$baz[1]}n";
?>

The above example will output:

I am bar.
I am bar.

Note:

Functions, method calls, static class variables, and class constants inside {$} work since PHP 5. However, the value accessed will be interpreted as the name of a variable in the scope in which the string is defined. Using single curly braces ({}) will not work for accessing the return values of functions or methods or the values of class constants or static class variables.

<?php
// Show all errors.
error_reporting(E_ALL);

class beers {
    const softdrink = 'rootbeer';
    public static $ale = 'ipa';
}

$rootbeer = 'A & W';
$ipa = 'Alexander Keith's';

// This works; outputs: I'd like an A & W
echo "I'd like an {${beers::softdrink}}n";

// This works too; outputs: I'd like an Alexander Keith's
echo "I'd like an {${beers::$ale}}n";
?>

String access and modification by character

Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string using square array brackets, as in $str[42]. Think of a string as an array of characters for this purpose. The functions substr() and substr_replace() can be used when you want to extract or replace more than 1 character.

Note: Strings may also be accessed using braces, as in $str{42}, for the same purpose.

Warning

Writing to an out of range offset pads the string with spaces. Non-integer types are converted to integer. Illegal offset type emits E_NOTICE. Negative offset emits E_NOTICE in write but reads empty string. Only the first character of an assigned string is used. Assigning empty string assigns NULL byte.

Warning

Internally, PHP strings are byte arrays. As a result, accessing or modifying a string using array brackets is not multi-byte safe, and should only be done with strings that are in a single-byte encoding such as ISO-8859-1.

Example #9 Some string examples

<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str[0];

// Get the third character of a string
$third = $str[2];

// Get the last character of a string.
$str = 'This is still a test.';
$last = $str[strlen($str)-1]; 

// Modify the last character of a string
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';

?>

As of PHP 5.4 string offsets have to either be integers or integer-like strings, otherwise a warning will be thrown. Previously an offset like “foo” was silently cast to 0.

Example #10 Differences between PHP 5.3 and PHP 5.4

<?php
$str 
= 'abc';

var_dump($str['1']);
var_dump(isset($str['1']));

var_dump($str['1.0']);
var_dump(isset($str['1.0']));

var_dump($str['x']);
var_dump(isset($str['x']));

var_dump($str['1x']);
var_dump(isset($str['1x']));
?>

Output of the above example in PHP 5.3:

string(1) "b"
bool(true)
string(1) "b"
bool(true)
string(1) "a"
bool(true)
string(1) "b"
bool(true)

Output of the above example in PHP 5.4:

string(1) "b"
bool(true)

Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
string(1) "b"
bool(false)

Warning: Illegal string offset 'x' in /tmp/t.php on line 9
string(1) "a"
bool(false)
string(1) "b"
bool(false)

Note:

Accessing variables of other types (not including arrays or objects implementing the appropriate interfaces) using [] or {} silently returns NULL.

Note:

PHP 5.5 added support for accessing characters within string literals using [] or {}.

Useful functions and operators

Strings may be concatenated using the ’.’ (dot) operator. Note that the ’+’ (addition) operator will not work for this. See String operators for more information.

There are a number of useful functions for string manipulation.

See the string functions section for general functions, and the regular expression functions or the Perl-compatible regular expression functions for advanced find & replace functionality.

There are also functions for URL strings, and functions to encrypt/decrypt strings (mcrypt and mhash).

Finally, see also the character type functions.

Converting to string

A value can be converted to a string using the (string) cast or the strval() function. String conversion is automatically done in the scope of an expression where a string is needed. This happens when using the echo or print functions, or when a variable is compared to a string. The sections on Types and Type Juggling will make the following clearer. See also the settype() function.

A boolean TRUE value is converted to the string “1”. Boolean FALSE is converted to “” (the empty string). This allows conversion back and forth between boolean and string values.

An integer or float is converted to a string representing the number textually (including the exponent part for floats). Floating point numbers can be converted using exponential notation (4.1E+6).

Note:

The decimal point character is defined in the script’s locale (category LC_NUMERIC). See the setlocale() function.

Arrays are always converted to the string “Array”; because of this, echo and print can not by themselves show the contents of an array. To view a single element, use a construction such as echo $arr[‘foo’]. See below for tips on viewing the entire contents.

Objects in PHP 4 are always converted to the string “Object”. To print the values of object properties for debugging reasons, read the paragraphs below. To get an object’s class name, use the get_class() function. As of PHP 5, the __toString method is used when applicable.

Resources are always converted to strings with the structure “Resource id #1”, where 1 is the unique number assigned to the resource by PHP at runtime. Do not rely upon this structure; it is subject to change. To get a resource’s type, use the get_resource_type() function.

NULL is always converted to an empty string.

As stated above, directly converting an array, object, or resource to a string does not provide any useful information about the value beyond its type. See the functions print_r() and var_dump() for more effective means of inspecting the contents of these types.

Most PHP values can also be converted to strings for permanent storage. This method is called serialization, and is performed by the serialize() function. If the PHP engine was built with WDDX support, PHP values can also be serialized as well-formed XML text.

String conversion to numbers

When a string is evaluated in a numeric context, the resulting value and type are determined as follows.

If the string does not contain any of the characters ’.’, ‘e’, or ‘E’ and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.

The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an ‘e’ or ‘E’ followed by one or more digits.

<?php
$foo 
= 1 + "10.5";                // $foo is float (11.5)
$foo = 1 + "-1.3e3";              // $foo is float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo is integer (1)
$foo = 1 + "bob3";                // $foo is integer (1)
$foo = 1 + "10 Small Pigs";       // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1;          // $foo is float (11)
$foo = "10.0 pigs " + 1.0;        // $foo is float (11)     
?>

For more information on this conversion, see the Unix manual page for strtod(3).

To test any of the examples in this section, cut and paste the examples and insert the following line to see what’s going on:

<?php
echo "$foo==$foo; type is " . gettype ($foo) . "<br />n";
?>

Do not expect to get the code of one character by converting it to integer, as is done in C. Use the ord() and chr() functions to convert between ASCII codes and characters.

Details of the String Type

The string in PHP is implemented as an array of bytes and an integer indicating the length of the buffer. It has no information about how those bytes translate to characters, leaving that task to the programmer. There are no limitations on the values the string can be composed of; in particular, bytes with value 0 (“NUL bytes”) are allowed anywhere in the string (however, a few functions, said in this manual not to be “binary safe”, may hand off the strings to libraries that ignore data after a NUL byte.)

This nature of the string type explains why there is no separate “byte” type in PHP – strings take this role. Functions that return no textual data – for instance, arbitrary data read from a network socket – will still return strings.

Given that PHP does not dictate a specific encoding for strings, one might wonder how string literals are encoded. For instance, is the string “á” equivalent to “xE1” (ISO-8859-1), “xC3xA1” (UTF-8, C form), “x61xCCx81” (UTF-8, D form) or any other possible representation? The answer is that string will be encoded in whatever fashion it is encoded in the script file. Thus, if the script is written in ISO-8859-1, the string will be encoded in ISO-8859-1 and so on. However, this does not apply if Zend Multibyte is enabled; in that case, the script may be written in an arbitrary encoding (which is explicity declared or is detected) and then converted to a certain internal encoding, which is then the encoding that will be used for the string literals. Note that there are some constraints on the encoding of the script (or on the internal encoding, should Zend Multibyte be enabled) – this almost always means that this encoding should be a compatible superset of ASCII, such as UTF-8 or ISO-8859-1. Note, however, that state-dependent encodings where the same byte values can be used in initial and non-initial shift states may be problematic.

Of course, in order to be useful, functions that operate on text may have to make some assumptions about how the string is encoded. Unfortunately, there is much variation on this matter throughout PHP’s functions:

  • Some functions assume that the string is encoded in some (any) single-byte encoding, but they do not need to interpret those bytes as specific characters. This is case of, for instance, substr(), strpos(), strlen() or strcmp(). Another way to think of these functions is that operate on memory buffers, i.e., they work with bytes and byte offsets.
  • Other functions are passed the encoding of the string, possibly they also assume a default if no such information is given. This is the case of htmlentities() and the majority of the functions in the mbstring extension.
  • Others use the current locale (see setlocale()), but operate byte-by-byte. This is the case of strcasecmp(), strtoupper() and ucfirst(). This means they can be used only with single-byte encodings, as long as the encoding is matched by the locale. For instance strtoupper(“á”) may return “Á” if the locale is correctly set and á is encoded with a single byte. If it is encoded in UTF-8, the correct result will not be returned and the resulting string may or may not be returned corrupted, depending on the current locale.
  • Finally, they may just assume the string is using a specific encoding, usually UTF-8. This is the case of most functions in the intl extension and in the PCRE extension (in the last case, only when the u modifier is used). Although this is due to their special purpose, the function utf8_decode() assumes a UTF-8 encoding and the function utf8_encode() assumes an ISO-8859-1 encoding.

Ultimately, this means writing correct programs using Unicode depends on carefully avoiding functions that will not work and that most likely will corrupt the data and using instead the functions that do behave correctly, generally from the intl and mbstring extensions. However, using functions that can handle Unicode encodings is just the beginning. No matter the functions the language provides, it is essential to know the Unicode specification. For instance, a program that assumes there is only uppercase and lowercase is making a wrong assumption.

 
 

지금에 와서야 CGI(12)는 퇴물로 분류된다. PHP(12), ASP와 같은 훌륭한 서버사이트 스크립트언어의 등장으로 동적인 페이지를 쉽게 작성하는데, 굳이 다루기 힘들고 까다로운 언어를 이용해서 CGI프로그래밍을 시도해야하는 필요가 사라졌기 때문이다.

그러나 여전히 보안, 기존 제품과의 호환, 기타 필요에 의해서 CGI에 대한 수요가 발생한다. 이번 글은 CGI의 개념과 CGI 애플리케이션의 작성에 대해서 알아보도록 하겠다. 그리고 글의 마지막에는 아파치 웹서버에서 우리가 작성한 CGI 애플리케이션을 작동시키도록 하겠다.


1. CGI 소개

CGI는 Common Gateway Interface의 줄임말인데, information 서버(와 외부 애플리케이션과의 인터페이스를 위한 표준 방법이다. information 서버의 가장 대표적인 예는 웹서버이다. 일반적인 plain HTML(12) 문서가 웹서버를 통해서 서비스된다면 이 내용은 “정적"데이터가 된다. 웹 프로그래머가 문서를 직접 수정하기전에는 어떤 웹서퍼가 어떤 시간에 문서를 보더라도 동일한 문서를 받아보게 된다.

몇년전만 해도 이러한 plain HTML문서만으로도 훌륭한 웹 서비스를 제공할 수 있었으나, 요즘의 웹서비스는 대부분 상호 작용적인 것이다. 이를테면 고객의 정보를 확인해서 고객마다 각각 다른 정보를 지닌 페이지를 뿌려주는 등의 서비스가 필요해진 것이다. CGI는 이러한 동적페이지 서비스를 위해서 만들어졌다.

CGI프로그램은 웹서버에 의해서 모듈 혹은 프로그램 형태로 실행되며, 데이터베이스에 연결해서 데이터를 읽어와서 웹페이지로 출력하거나, 데이터를 저장하는 등의 일을 한다. 중간에서 데이터를 중계하는 이러한 프로그램의 특징 때문에 Gateway라는 이름이 붙었다. 현재 CGI의 버젼은 1.1까지 나와 있다.

참고: CGI은 인터페이스다. 라이브러리나 함수가 아니다.

CGI는 기본적으로 당신의 시스템에서 실행되어지는 프로그램으로 다른 프로그램(vi, ls ..)들과 전혀 다를바가 없다. 다른 프로그램들이 출력결과를 표준출력을 통해서 전달하는 것과는 달리 CGI는 출력결과를 웹서버로 전달한다는 정도만 약간 다르다고 보면 된다.

만약 당신이 Apache(12) HTTPD 서버를 사용하고 있다면, 작성된 CGI 프로그램들은 /cgi-bin 에 위치할 것이다. CGI프로그래밍은 다음과 같은 다양한 언어를 통해서 작성가능 하다.

  • C/C++

  • PHP(12)

  • Perl

  • TCL

  • Python

  • Ruby

  • 모든 종류의 유닉스 Shell Script

  • Visual Basic

  • AppleScript

결론적으로 말하자면 어떠한 언어를 쓰더라도 CGI규격만 지킨다면 CGI프로그램작성을 위해서 사용할 수 있다. 만약 C와 C++같은 언어를 이용해서 개발한다면 컴파일을 시켜서 제대로 실행되는지 먼저 테스트해봐야 할 것이다. Perl이나 shell과 같은 스크립트 언어를 이용한다면 컴파일시키지 않아도 되므로 좀더 편하게 프로그래밍 가능할 것이다. 이런 이유로 스크립트 언어가 과거에 CGI를 위해서 널리 사용되었다. Perl의 경우에는 범용 언어로 개발되었지만 특유의 강력한 문자열 처리 능력으로 인하여 특히 CGI프로그래밍을 위한 언어로 널리 사용되었다.

컴파일 된 실행파일이나, 스크립트들은 /cgi-bin에 옮겨 놓고 웹페이지를 통해서 불러들이면 웹서버가 알아서 실행시키게 된다.


1.1. PHP(12), ASP와 CGI(12)

참고로 PHP(12)와 ASP같은 경우 자체적으로 CGI를 만족한다. CGI규격을 엔진내부에서 알아서 처리해 주므로 개발자는 CGI에 대해서 골치아프게 머리 쓸필요 없이 구현 자체에 집중할 수 있다.

그러나 PHP(12)와 ASP의 경우 웹서버의 모듈로서 작동하는데 이는 고전적인 CGI프로그램들과는 틀린 작동방식이다. 그러므로 이하 CGI를 설명하는데 있어서는 PHP(12)와 ASP는 예외로 하고 설명하도록 하겠다.


2. CGI 프로그래밍

2.1. 작동방식(입/출력)

웹서버에서 CGI 프로그램은 fork()를 통해서 실행시키며 CGI에 데이터를 전달하기 위해서 표준출력과 환경변수를 사용하며, CGI프로그램으로 부터 데이터를 전달받기 위해서 표준입력을 사용한다.

웹서버에서 CGI프로그램을 실행시킬 때는 여러가지 정보도 CGI프로그램에 전달할 것이다. 전달방식은 GET, POST방식이 대표적이다. GET방식의 데이터 요청에서 이루어진 URI값은 화경변수를 통해서, POST방식은 표준입력을 통해서 CGI프로그램으로 넘어간다.

<img src=http://www.joinc.co.kr/albums/album01/aik.gif>

			

2.1.1. GET 방식

GET방식은 URI를 통해서 필요한 데이터를 요청하는 방식이다.

http://www.joinc.co.kr/modules.php?op=modload&name=Forum&file=viewtopic&topic=29106

				

웹서버는 GET방식을 통해서 입력받은 데이터를 환경변수를 통해서 CGI프로그램에 전달한다. CGI프로그램은 환경변수를 읽어들여서 필요한 작업을 하게 된다. C에서는 getenv()를 통해서 환경변수를 읽어들 일 수 있다. 다음은 위의 URI로 전달된 값을 각 언어별 환경변수를 읽어들이는 방법이다.

perl

===========

print $ENV{'QUERY_STRING'};    # modload



C/C++

============

char *value;

value = getenv("QUERY_STRING");    // modload



Shell

============

echo $QUERY_STRING        # modload

				

이렇게 하면 쿼리 문자열인 "op=modload&name=Forum&file=viewtopic&topic=29106"가 넘어오고 이것을 적당히 파싱해서 사용하면 된다.

환경변수는 프로세스의 스택영역에 위치한다. 그러므로 전달할 수 있는 데이터의 양에 제한이 생긴다(제한을 아시는 분의 답변 부탁드립니다).


2.1.2. POST 방식

POST 방식은 웹에서 <form>을 통해서 전달되는 값들로 CGI프로그램으로는 표준입력을 통해서 전달된다. 경변수에 의해서 제한이 생기는 GET방식에 비해서 전달할 수 있는 데이터의 양에 제약없이 사용가능하다. GET과 마찬가지로 POST방식역시 경우 프로그램에서 문자열 파싱을 해줘야 한다. 이건 상당히 귀찮은 작업이 될 수 있다. 이러한 귀찮은 작업을 대신 처리해줄 라이브러리가 여럿 존재하는데, 문서의 마지막에 따로 언급하도록 하겠다.


2.2. CGI 환경 변수

CGI 프로그램의 경우 단독프로세스로 작동하기 때문에, 자신을 실행시킨 웹서버의 여러가지 정보를 어떡해서든지 유지할 수 있어야 한다. 이를테면 웹서버의 종류가 무엇인지, 어떤 URL(12)이 웹에 접근을 해서 CGI 프로그램을 가동시켰는지, 어떤 쿼리 문자열을 보냈는지, GET을 이용했는지 POST를 이용했는지 등등의 정보를 웹서버로 부터 상속받아야 한다.

이러한 모든 정보는 약속된 CGI 환경변수를 통해서 읽어 올 수 있다. 현재 CGI 환경변수에는 다음과 같은 것들이 정의되어 있다.

		

   DOCUMENT_ROOT           // 문서가 위치하는 루트 디렉토리

   GATEWAY_INTERFACE       // 사용된 gateway 인터페이스 (이경우 CGI 1.1) 

   HTTP_ACCEPT 

   HTTP_REFERER            // POST방식일 경우 요청한 페이지 이름

   HTTP_ACCEPT_CHARSET 

   HTTP_ACCEPT_LANGUAGE 

   HTTP_CONNECTION         // 연결방식 (보통 Keep-Alive) 

   HTTP_HOST               // 웹서버의 IP와 PORT정보 

   HTTP_USER_AGENT         // 연결에 사용한 브라우저 정보

   PATH                    // 실행파일 경로 

   QUERY_STRING            // 쿼리 문자열 

   REMOTE_ADDR             // 클라이언트 주소

   REMOTE_HOST	            

   REMOTE_PORT             // 클라이언트 포트

   REQUEST_METHOD          // 요청방법, 보통 GET이나 POST

   REQUEST_URI             // URI정보

   SCRIPT_FILENAME 

   SCRIPT_NAME             // 실행한 CGI 프로그램 이름 

   SERVER_ADMIN            // 서버관리자 정보, 보통 email주소

   SERVER_NAME             // 서버이름, 보통 도메인이름

   SERVER_PORT             // 서비스 포트(80, 8080)

   SERVER_PROTOCOL         // 서비스 프로토콜(HTTP1.0, HTTP1.1)

   SERVER_SOFTWARE         // 서버 프로그램

   TZ                      // 타임존

			

2.3. CGI 테스트 프로그램 – GET 방식

그럼 간단한 CGI테스트 프로그램을 하나 만들어 보도록 하겠다. 이 프로그램은 현재 시간과 함께 쿼리 스트링과 기타 CGI환경변수를 출력하는 일을 한다.

	

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <sys/types.h>

#include <unistd.h>



static char dday[256];

static char wday[7][2] = {"일","월", "화", "수", "목", "금", "토"};



char * time2str(time_t, char * );



char * time2str(time_t org_time, char *format)

{

    struct tm *tm_ptr;

    int index=0;

    int i;

    tm_ptr = localtime(&org_time);

    memset(dday, 0x00, 256);

    for (i = 0; i < strlen(format); i++)

    {

        switch(format[i])

        {

            case 'y': // 년                                        

                sprintf(dday+index, "%04d", tm_ptr->tm_year+1900);

                index += 4;

                break;

            case 'm': // 월(1-12), 분(0-59)

                if (format[i+1] == 'i')

                {

                    sprintf(dday+index, "%02d", tm_ptr->tm_min);

                    index += 2;

                    i++;

                    break;

                }

                else

                {

                    sprintf(dday+index, "%02d", tm_ptr->tm_mon+1);

                    index += 2;

                    break;

                }

            case 'd': // 일 (1-31)                                

                sprintf(dday+index, "%02d", tm_ptr->tm_mday);

                index += 2;

                break;

            case 'D': // 요일(일 ~ 토)                            

                sprintf(dday+index, "%s", wday[tm_ptr->tm_wday]);

                index += 2;

                break;

            case 'h': // 시(00-23)                                

                sprintf(dday+index, "%02d", tm_ptr->tm_hour);

                index += 2;

                break;

            case 's': // 초(00-59)                                

                sprintf(dday+index, "%02d", tm_ptr->tm_sec);

                index += 2;

                break;



            default:

                dday[index] = format[i];

                index++;

        }

    }

    return dday;

}



void print_header()

{

    printf("Content-type: text/htmlnn");

}



int main(int argc, char ** argv)

{

    print_header(); // 반드시 포함되어야 한다.

    printf("<h2>Hello World CGI VERSION : %s</h2>n",

            time2str( time((time_t *)NULL), "y년 m월 d일 D요일 h:mi:s"));

    printf("Query String %s<br>n", getenv("QUERY_STRING"));



    printf("SERVER_SOFTWARE = %s<br>n", getenv("SERVER_SOFTWARE"));

    printf("GATEWAY_INTERFACE = %s<br>n", getenv("GATEWAY_INTERFACE"));

    printf("SERVER_PROTOCOL = %s<br>n", getenv("SERVER_PROTOCOL"));

    printf("HTTP_ACCEPT = %s<br>n", getenv("HTTP_ACCEPT"));

    printf("REQUEST_METHOD = %s<br>n", getenv("REQUEST_METHOD"));

    printf("REMOTE_ADDR = %sn", getenv("REMOTE_ADDR"));

    printf("<br><br>n");

}

			

위 코드를 컴파일 한뒤 웹서버의 cgi-bin에 test 라는 이름으로 복사한다음 http://hostname/cgi-bin/test?name=yundream으로 테스트 해보도록 하자.

Hello World CGI VERSION : 2004년 05월 11일 화요일 11:10:27



Query String name=yundream

SERVER_SOFTWARE = Apache/1.3.26 (Unix) PHP(12)/4.3.0

GATEWAY_INTERFACE = CGI/1.1

SERVER_PROTOCOL = HTTP/1.0

HTTP_ACCEPT = text/*, image/*, audio/*, application/*

REQUEST_METHOD = GET

REMOTE_ADDR = 192.168.1.101

			

2.4. CGI 테스트 프로그램 – POST 방식

POST 방식이란 URI를 통해서 데이터를 넘기는 방식이 아닌 <form>을 통해서 데이터를 넘기는 방식을 뜻한다. CGI 프로그램에서는 표준입력으로 받을 수 있다. 다음은 POST 방식 테스트를 위한 웹페이지이다. HTML 코드는 설명 생략하도록 하겠다. 페이지의 이름은 post.php로 하겠다.

<form action=/cgi-bin/post-cgi method=post>

이름 : <input type=text name=name size=16><br>

나이 : <input type=text name=age  size=16><br>

<input type=submit name=submit>

</form>

			

다음은 POST방식으로 넘어온 데이터를 받기 위한 프로그램이다. 간단하므로 역시 설명은 생략하도록 하겠다.

#include <stdio.h>

#include <string.h>



int main(int argc, char **argv)

{

    char buf[1024]; 

    int n;   

    printf("Content-type: text/htmlnn");

    printf("Referer 페이지 %s<br><br>", getenv("HTTP_REFERER"));

    memset(buf, 0x00, 1024);

    while((n = read(0, buf, 1023)) > 0) 

    {

        printf("POST DATA : %s", buf); 

        memset(buf, 0x00, 1024); 

    } 

}

			

브라우저에서 post.php를 부른다음 적당한 값을 넣고 실행시키면 다음과 같은 결과가 출력될 것이다.

Referer 페이지 http://localhost/post.php



POST DATA : name=yundream&age=21&submit=SUBMIT

			

쿼리 문자열을 읽어들이는 방법외에 쿼리 문자열의 구성은 GET방식과 동일함을 알 수 있다. 물론 키와 값을 제대로 얻기 위해서는 ’=’,’&‘를 기준으로 파싱해줘야 하겠지만 말이다.


2.5. 쿼리 문자열 분석

쿼리 문자열을 분석은 언뜻 보면 별로 어려울 것 같지 않다. 귀찮을 수는 있겠지만 ’=’,’&’을 기준으로 파싱하는 건 기술적으로 어려운 문제는 아니기 때문이다.

그러나 알고보면 그렇게 간단하지가 않다. post.php에서 name에 yun&dream 과 같이 쿼리 스트링 분리를 위한 특수문자가 포함되어 버리는 경우를 생각해 보자. 당연히 제대로 처리 할 수 없을 것이다. 이러한 이유로 웹에서 POST, GET방식으로 데이터를 전달할 때는 인코딩과정이 필요하게 된다. 실제 post.php에 yun&dream을 입력한다음 submit 버튼을 누르면 다음과 같이 인코딩된 결과가 표시된다.

Referer 페이지 http://www.joinc.co.kr/post.php



POST DATA : name=yun%26dream&age=21&submit=SUBMIT

			

&이 %25 으로 인코딩 되어 있음을 알 수 있다. 웹에서 값의 전달을 위해서 사용하는 이러한 인코딩 방식을 urlencode 라고 한다.

urlencode는 단지 &, = 만을 인코딩하지 않는다. [[HTML([a-zA-Z0-9-._])]]을 제외한 모든 문자들을 변환한다. 변환 방법은 다음과 같다.

	

% + 해당문자의 HEX값

			

예를 들어서 * 는 %2A 로 ( 는 %28 로 변환된다. ASCII 테이블은 ascii table를 참고하기 바란다.

그러므로 CGI 프로그램에는 이들 urlencode된 데이터를 decode하기 위한 코드가 포함되어야 한다. encode규칙만 안다면 decode 코드는 어렵지 않게 작성할 수 있을 것이다. urlencode 관련된 코드를 Code_C_urlencode에 정리해 두었으니 한번 참고해 보기 바란다.


2.6. CGI 관련 라이브러리

제대로된 CGI 프로그램을 짤려면 이것 저것 신경써야 할게 한두가지가 아니다. HTTP 프로토콜, Cookie, POST, GET, MIME, uuencode, 파일전송 … 이것을 일일이 작성하기란 여간 까다로운게 아니다. 그래서 CGI 프로그래밍 관련 몇 가지 라이브러리를 소개하고 글을 마치고자 한다.

 
 

지금에 와서야 CGI(12)는 퇴물로 분류된다. PHP(12), ASP와 같은 훌륭한 서버사이트 스크립트언어의 등장으로 동적인 페이지를 쉽게 작성하는데, 굳이 다루기 힘들고 까다로운 언어를 이용해서 CGI프로그래밍을 시도해야하는 필요가 사라졌기 때문이다.

그러나 여전히 보안, 기존 제품과의 호환, 기타 필요에 의해서 CGI에 대한 수요가 발생한다. 이번 글은 CGI의 개념과 CGI 애플리케이션의 작성에 대해서 알아보도록 하겠다. 그리고 글의 마지막에는 아파치 웹서버에서 우리가 작성한 CGI 애플리케이션을 작동시키도록 하겠다.


1. CGI 소개

CGI는 Common Gateway Interface의 줄임말인데, information 서버(와 외부 애플리케이션과의 인터페이스를 위한 표준 방법이다. information 서버의 가장 대표적인 예는 웹서버이다. 일반적인 plain HTML(12) 문서가 웹서버를 통해서 서비스된다면 이 내용은 “정적"데이터가 된다. 웹 프로그래머가 문서를 직접 수정하기전에는 어떤 웹서퍼가 어떤 시간에 문서를 보더라도 동일한 문서를 받아보게 된다.

몇년전만 해도 이러한 plain HTML문서만으로도 훌륭한 웹 서비스를 제공할 수 있었으나, 요즘의 웹서비스는 대부분 상호 작용적인 것이다. 이를테면 고객의 정보를 확인해서 고객마다 각각 다른 정보를 지닌 페이지를 뿌려주는 등의 서비스가 필요해진 것이다. CGI는 이러한 동적페이지 서비스를 위해서 만들어졌다.

CGI프로그램은 웹서버에 의해서 모듈 혹은 프로그램 형태로 실행되며, 데이터베이스에 연결해서 데이터를 읽어와서 웹페이지로 출력하거나, 데이터를 저장하는 등의 일을 한다. 중간에서 데이터를 중계하는 이러한 프로그램의 특징 때문에 Gateway라는 이름이 붙었다. 현재 CGI의 버젼은 1.1까지 나와 있다.

참고: CGI은 인터페이스다. 라이브러리나 함수가 아니다.

CGI는 기본적으로 당신의 시스템에서 실행되어지는 프로그램으로 다른 프로그램(vi, ls ..)들과 전혀 다를바가 없다. 다른 프로그램들이 출력결과를 표준출력을 통해서 전달하는 것과는 달리 CGI는 출력결과를 웹서버로 전달한다는 정도만 약간 다르다고 보면 된다.

만약 당신이 Apache(12) HTTPD 서버를 사용하고 있다면, 작성된 CGI 프로그램들은 /cgi-bin 에 위치할 것이다. CGI프로그래밍은 다음과 같은 다양한 언어를 통해서 작성가능 하다.

  • C/C++

  • PHP(12)

  • Perl

  • TCL

  • Python

  • Ruby

  • 모든 종류의 유닉스 Shell Script

  • Visual Basic

  • AppleScript

결론적으로 말하자면 어떠한 언어를 쓰더라도 CGI규격만 지킨다면 CGI프로그램작성을 위해서 사용할 수 있다. 만약 C와 C++같은 언어를 이용해서 개발한다면 컴파일을 시켜서 제대로 실행되는지 먼저 테스트해봐야 할 것이다. Perl이나 shell과 같은 스크립트 언어를 이용한다면 컴파일시키지 않아도 되므로 좀더 편하게 프로그래밍 가능할 것이다. 이런 이유로 스크립트 언어가 과거에 CGI를 위해서 널리 사용되었다. Perl의 경우에는 범용 언어로 개발되었지만 특유의 강력한 문자열 처리 능력으로 인하여 특히 CGI프로그래밍을 위한 언어로 널리 사용되었다.

컴파일 된 실행파일이나, 스크립트들은 /cgi-bin에 옮겨 놓고 웹페이지를 통해서 불러들이면 웹서버가 알아서 실행시키게 된다.


1.1. PHP(12), ASP와 CGI(12)

참고로 PHP(12)와 ASP같은 경우 자체적으로 CGI를 만족한다. CGI규격을 엔진내부에서 알아서 처리해 주므로 개발자는 CGI에 대해서 골치아프게 머리 쓸필요 없이 구현 자체에 집중할 수 있다.

그러나 PHP(12)와 ASP의 경우 웹서버의 모듈로서 작동하는데 이는 고전적인 CGI프로그램들과는 틀린 작동방식이다. 그러므로 이하 CGI를 설명하는데 있어서는 PHP(12)와 ASP는 예외로 하고 설명하도록 하겠다.


2. CGI 프로그래밍

2.1. 작동방식(입/출력)

웹서버에서 CGI 프로그램은 fork()를 통해서 실행시키며 CGI에 데이터를 전달하기 위해서 표준출력과 환경변수를 사용하며, CGI프로그램으로 부터 데이터를 전달받기 위해서 표준입력을 사용한다.

웹서버에서 CGI프로그램을 실행시킬 때는 여러가지 정보도 CGI프로그램에 전달할 것이다. 전달방식은 GET, POST방식이 대표적이다. GET방식의 데이터 요청에서 이루어진 URI값은 화경변수를 통해서, POST방식은 표준입력을 통해서 CGI프로그램으로 넘어간다.

<img src=http://www.joinc.co.kr/albums/album01/aik.gif>

			

2.1.1. GET 방식

GET방식은 URI를 통해서 필요한 데이터를 요청하는 방식이다.

http://www.joinc.co.kr/modules.php?op=modload&name=Forum&file=viewtopic&topic=29106

				

웹서버는 GET방식을 통해서 입력받은 데이터를 환경변수를 통해서 CGI프로그램에 전달한다. CGI프로그램은 환경변수를 읽어들여서 필요한 작업을 하게 된다. C에서는 getenv()를 통해서 환경변수를 읽어들 일 수 있다. 다음은 위의 URI로 전달된 값을 각 언어별 환경변수를 읽어들이는 방법이다.

perl

===========

print $ENV{'QUERY_STRING'};    # modload



C/C++

============

char *value;

value = getenv("QUERY_STRING");    // modload



Shell

============

echo $QUERY_STRING        # modload

				

이렇게 하면 쿼리 문자열인 "op=modload&name=Forum&file=viewtopic&topic=29106"가 넘어오고 이것을 적당히 파싱해서 사용하면 된다.

환경변수는 프로세스의 스택영역에 위치한다. 그러므로 전달할 수 있는 데이터의 양에 제한이 생긴다(제한을 아시는 분의 답변 부탁드립니다).


2.1.2. POST 방식

POST 방식은 웹에서 <form>을 통해서 전달되는 값들로 CGI프로그램으로는 표준입력을 통해서 전달된다. 경변수에 의해서 제한이 생기는 GET방식에 비해서 전달할 수 있는 데이터의 양에 제약없이 사용가능하다. GET과 마찬가지로 POST방식역시 경우 프로그램에서 문자열 파싱을 해줘야 한다. 이건 상당히 귀찮은 작업이 될 수 있다. 이러한 귀찮은 작업을 대신 처리해줄 라이브러리가 여럿 존재하는데, 문서의 마지막에 따로 언급하도록 하겠다.


2.2. CGI 환경 변수

CGI 프로그램의 경우 단독프로세스로 작동하기 때문에, 자신을 실행시킨 웹서버의 여러가지 정보를 어떡해서든지 유지할 수 있어야 한다. 이를테면 웹서버의 종류가 무엇인지, 어떤 URL(12)이 웹에 접근을 해서 CGI 프로그램을 가동시켰는지, 어떤 쿼리 문자열을 보냈는지, GET을 이용했는지 POST를 이용했는지 등등의 정보를 웹서버로 부터 상속받아야 한다.

이러한 모든 정보는 약속된 CGI 환경변수를 통해서 읽어 올 수 있다. 현재 CGI 환경변수에는 다음과 같은 것들이 정의되어 있다.

		

   DOCUMENT_ROOT           // 문서가 위치하는 루트 디렉토리

   GATEWAY_INTERFACE       // 사용된 gateway 인터페이스 (이경우 CGI 1.1) 

   HTTP_ACCEPT 

   HTTP_REFERER            // POST방식일 경우 요청한 페이지 이름

   HTTP_ACCEPT_CHARSET 

   HTTP_ACCEPT_LANGUAGE 

   HTTP_CONNECTION         // 연결방식 (보통 Keep-Alive) 

   HTTP_HOST               // 웹서버의 IP와 PORT정보 

   HTTP_USER_AGENT         // 연결에 사용한 브라우저 정보

   PATH                    // 실행파일 경로 

   QUERY_STRING            // 쿼리 문자열 

   REMOTE_ADDR             // 클라이언트 주소

   REMOTE_HOST	            

   REMOTE_PORT             // 클라이언트 포트

   REQUEST_METHOD          // 요청방법, 보통 GET이나 POST

   REQUEST_URI             // URI정보

   SCRIPT_FILENAME 

   SCRIPT_NAME             // 실행한 CGI 프로그램 이름 

   SERVER_ADMIN            // 서버관리자 정보, 보통 email주소

   SERVER_NAME             // 서버이름, 보통 도메인이름

   SERVER_PORT             // 서비스 포트(80, 8080)

   SERVER_PROTOCOL         // 서비스 프로토콜(HTTP1.0, HTTP1.1)

   SERVER_SOFTWARE         // 서버 프로그램

   TZ                      // 타임존

			

2.3. CGI 테스트 프로그램 – GET 방식

그럼 간단한 CGI테스트 프로그램을 하나 만들어 보도록 하겠다. 이 프로그램은 현재 시간과 함께 쿼리 스트링과 기타 CGI환경변수를 출력하는 일을 한다.

	

#include <stdio.h>

#include <string.h>

#include <time.h>

#include <sys/types.h>

#include <unistd.h>



static char dday[256];

static char wday[7][2] = {"일","월", "화", "수", "목", "금", "토"};



char * time2str(time_t, char * );



char * time2str(time_t org_time, char *format)

{

    struct tm *tm_ptr;

    int index=0;

    int i;

    tm_ptr = localtime(&org_time);

    memset(dday, 0x00, 256);

    for (i = 0; i < strlen(format); i++)

    {

        switch(format[i])

        {

            case 'y': // 년                                        

                sprintf(dday+index, "%04d", tm_ptr->tm_year+1900);

                index += 4;

                break;

            case 'm': // 월(1-12), 분(0-59)

                if (format[i+1] == 'i')

                {

                    sprintf(dday+index, "%02d", tm_ptr->tm_min);

                    index += 2;

                    i++;

                    break;

                }

                else

                {

                    sprintf(dday+index, "%02d", tm_ptr->tm_mon+1);

                    index += 2;

                    break;

                }

            case 'd': // 일 (1-31)                                

                sprintf(dday+index, "%02d", tm_ptr->tm_mday);

                index += 2;

                break;

            case 'D': // 요일(일 ~ 토)                            

                sprintf(dday+index, "%s", wday[tm_ptr->tm_wday]);

                index += 2;

                break;

            case 'h': // 시(00-23)                                

                sprintf(dday+index, "%02d", tm_ptr->tm_hour);

                index += 2;

                break;

            case 's': // 초(00-59)                                

                sprintf(dday+index, "%02d", tm_ptr->tm_sec);

                index += 2;

                break;



            default:

                dday[index] = format[i];

                index++;

        }

    }

    return dday;

}



void print_header()

{

    printf("Content-type: text/htmlnn");

}



int main(int argc, char ** argv)

{

    print_header(); // 반드시 포함되어야 한다.

    printf("<h2>Hello World CGI VERSION : %s</h2>n",

            time2str( time((time_t *)NULL), "y년 m월 d일 D요일 h:mi:s"));

    printf("Query String %s<br>n", getenv("QUERY_STRING"));



    printf("SERVER_SOFTWARE = %s<br>n", getenv("SERVER_SOFTWARE"));

    printf("GATEWAY_INTERFACE = %s<br>n", getenv("GATEWAY_INTERFACE"));

    printf("SERVER_PROTOCOL = %s<br>n", getenv("SERVER_PROTOCOL"));

    printf("HTTP_ACCEPT = %s<br>n", getenv("HTTP_ACCEPT"));

    printf("REQUEST_METHOD = %s<br>n", getenv("REQUEST_METHOD"));

    printf("REMOTE_ADDR = %sn", getenv("REMOTE_ADDR"));

    printf("<br><br>n");

}

			

위 코드를 컴파일 한뒤 웹서버의 cgi-bin에 test 라는 이름으로 복사한다음 http://hostname/cgi-bin/test?name=yundream으로 테스트 해보도록 하자.

Hello World CGI VERSION : 2004년 05월 11일 화요일 11:10:27



Query String name=yundream

SERVER_SOFTWARE = Apache/1.3.26 (Unix) PHP(12)/4.3.0

GATEWAY_INTERFACE = CGI/1.1

SERVER_PROTOCOL = HTTP/1.0

HTTP_ACCEPT = text/*, image/*, audio/*, application/*

REQUEST_METHOD = GET

REMOTE_ADDR = 192.168.1.101

			

2.4. CGI 테스트 프로그램 – POST 방식

POST 방식이란 URI를 통해서 데이터를 넘기는 방식이 아닌 <form>을 통해서 데이터를 넘기는 방식을 뜻한다. CGI 프로그램에서는 표준입력으로 받을 수 있다. 다음은 POST 방식 테스트를 위한 웹페이지이다. HTML 코드는 설명 생략하도록 하겠다. 페이지의 이름은 post.php로 하겠다.

<form action=/cgi-bin/post-cgi method=post>

이름 : <input type=text name=name size=16><br>

나이 : <input type=text name=age  size=16><br>

<input type=submit name=submit>

</form>

			

다음은 POST방식으로 넘어온 데이터를 받기 위한 프로그램이다. 간단하므로 역시 설명은 생략하도록 하겠다.

#include <stdio.h>

#include <string.h>



int main(int argc, char **argv)

{

    char buf[1024]; 

    int n;   

    printf("Content-type: text/htmlnn");

    printf("Referer 페이지 %s<br><br>", getenv("HTTP_REFERER"));

    memset(buf, 0x00, 1024);

    while((n = read(0, buf, 1023)) > 0) 

    {

        printf("POST DATA : %s", buf); 

        memset(buf, 0x00, 1024); 

    } 

}

			

브라우저에서 post.php를 부른다음 적당한 값을 넣고 실행시키면 다음과 같은 결과가 출력될 것이다.

Referer 페이지 http://localhost/post.php



POST DATA : name=yundream&age=21&submit=SUBMIT

			

쿼리 문자열을 읽어들이는 방법외에 쿼리 문자열의 구성은 GET방식과 동일함을 알 수 있다. 물론 키와 값을 제대로 얻기 위해서는 ’=’,’&‘를 기준으로 파싱해줘야 하겠지만 말이다.


2.5. 쿼리 문자열 분석

쿼리 문자열을 분석은 언뜻 보면 별로 어려울 것 같지 않다. 귀찮을 수는 있겠지만 ’=’,’&’을 기준으로 파싱하는 건 기술적으로 어려운 문제는 아니기 때문이다.

그러나 알고보면 그렇게 간단하지가 않다. post.php에서 name에 yun&dream 과 같이 쿼리 스트링 분리를 위한 특수문자가 포함되어 버리는 경우를 생각해 보자. 당연히 제대로 처리 할 수 없을 것이다. 이러한 이유로 웹에서 POST, GET방식으로 데이터를 전달할 때는 인코딩과정이 필요하게 된다. 실제 post.php에 yun&dream을 입력한다음 submit 버튼을 누르면 다음과 같이 인코딩된 결과가 표시된다.

Referer 페이지 http://www.joinc.co.kr/post.php



POST DATA : name=yun%26dream&age=21&submit=SUBMIT

			

&이 %25 으로 인코딩 되어 있음을 알 수 있다. 웹에서 값의 전달을 위해서 사용하는 이러한 인코딩 방식을 urlencode 라고 한다.

urlencode는 단지 &, = 만을 인코딩하지 않는다. [[HTML([a-zA-Z0-9-._])]]을 제외한 모든 문자들을 변환한다. 변환 방법은 다음과 같다.

	

% + 해당문자의 HEX값

			

예를 들어서 * 는 %2A 로 ( 는 %28 로 변환된다. ASCII 테이블은 ascii table를 참고하기 바란다.

그러므로 CGI 프로그램에는 이들 urlencode된 데이터를 decode하기 위한 코드가 포함되어야 한다. encode규칙만 안다면 decode 코드는 어렵지 않게 작성할 수 있을 것이다. urlencode 관련된 코드를 Code_C_urlencode에 정리해 두었으니 한번 참고해 보기 바란다.


2.6. CGI 관련 라이브러리

제대로된 CGI 프로그램을 짤려면 이것 저것 신경써야 할게 한두가지가 아니다. HTTP 프로토콜, Cookie, POST, GET, MIME, uuencode, 파일전송 … 이것을 일일이 작성하기란 여간 까다로운게 아니다. 그래서 CGI 프로그래밍 관련 몇 가지 라이브러리를 소개하고 글을 마치고자 한다.

http://sig3067.egloos.com/5699633 에서 참조

$_SERVER 또는 $HTTP_SERVER_VARS

웹서버에 의해 발생된 정보들….

$_ENV 또는 $HTTP_ENV_VARS

PHP가 실행되고 있는 환경에서 오는 정보들…

$_COOKIE 또는 $HTTP_COOKIE_VARS

쿠키의 내용들…

$_GET 또는 $HTTP_GET_VARS

GET으로 건내지는 정보들…

$_POST 또는 $HTTP_POST_VARS

POST로 건내지는 정보들…

$_FILES 또는 $HTTP_FILES_VARS

POST로 업로드되는 파일의정보들..

$_REQUEST 또는 $HTTP_REQUEST_VARS

$_GET, $_POST,$_COOKIE,$_FILES 의 내용들

$GLOBALS

글로벌스코프에 있는 모든 정보

$php_errormsg

같은 스코프내에서 발생한 가장 가까운 에러메세지

$php_errormsg를 유효로 하고싶으면 php.ini에서 track_errors=on 으로 설정해야함

이외에 $_SESSION이 있지만 이건 별도로 다루는게 좋을듯

아래와 같은 코드로 확인이 가능합니다.

$HTML_로 시작하는 변수는 함수나 메소드내에서는 “global $HTTP_SERVER_VARS"처럼 global을 앞에 붙여줘야함

PHP5에서는 $HTML_로 시작하는 변수는 php.ini에서 register_long_arrays = on 로 한 경우만 사용가능

http://sig3067.egloos.com/5699633 에서 참조

$_SERVER 또는 $HTTP_SERVER_VARS

웹서버에 의해 발생된 정보들….

$_ENV 또는 $HTTP_ENV_VARS

PHP가 실행되고 있는 환경에서 오는 정보들…

$_COOKIE 또는 $HTTP_COOKIE_VARS

쿠키의 내용들…

$_GET 또는 $HTTP_GET_VARS

GET으로 건내지는 정보들…

$_POST 또는 $HTTP_POST_VARS

POST로 건내지는 정보들…

$_FILES 또는 $HTTP_FILES_VARS

POST로 업로드되는 파일의정보들..

$_REQUEST 또는 $HTTP_REQUEST_VARS

$_GET, $_POST,$_COOKIE,$_FILES 의 내용들

$GLOBALS

글로벌스코프에 있는 모든 정보

$php_errormsg

같은 스코프내에서 발생한 가장 가까운 에러메세지

$php_errormsg를 유효로 하고싶으면 php.ini에서 track_errors=on 으로 설정해야함

이외에 $_SESSION이 있지만 이건 별도로 다루는게 좋을듯

아래와 같은 코드로 확인이 가능합니다.

$HTML_로 시작하는 변수는 함수나 메소드내에서는 “global $HTTP_SERVER_VARS"처럼 global을 앞에 붙여줘야함

PHP5에서는 $HTML_로 시작하는 변수는 php.ini에서 register_long_arrays = on 로 한 경우만 사용가능