output操作

output操作

1,创建一个新的扩展

./ext_skel --extname=output1

2,修改config.m4,去掉没用的注释语句

cd output1
vi config.m4

3,编写代码

vi output1.c
#修改confirm_output_compiled
PHP_FUNCTION(confirm_output_compiled)
{
    char *arg = NULL;
    int arg_len, len;
    char *strg;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
        return;
    }

    FILE *fp = NULL;
    long fsize;
    char *buffer;
    size_t result;

    fp = fopen(arg, "r");
    if (fp == NULL) {
        RETURN_FALSE;
    }

    fseek(fp, 0, SEEK_END);
    fsize = ftell(fp);
    rewind(fp);
    buffer = (char *)malloc(sizeof(char) * fsize);
    result = fread(buffer, 1, fsize, fp);
    fclose(fp);

    //输出Content-type
    char *content_type = "'Content-type: image/jpeg";
    sapi_header_line ctr = {0};
    ctr.line = content_type;
    ctr.line_len = strlen(content_type);
    ctr.response_code = 200;
    sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);

    //输出图像
    php_output_write(buffer, result TSRMLS_CC);
    php_output_end_all(TSRMLS_C);

    free(buffer);

    RETURN_TRUE;
}

4,结构

//1, 输出header操作
// SAPI.h
typedef struct {
    char *line;         //输出的内容,记得需要自已释放内存
    uint line_len;      //输出内容的长度
    long response_code; //状态码
} sapi_header_line;

typedef enum {                  /* Parameter:           */
    SAPI_HEADER_REPLACE,        /* sapi_header_line*    */
    SAPI_HEADER_ADD,            /* sapi_header_line*    */
    SAPI_HEADER_DELETE,         /* sapi_header_line*    */
    SAPI_HEADER_DELETE_ALL,     /* void                 */
    SAPI_HEADER_SET_STATUS      /* int                  */
} sapi_header_op_enum;

#调用sapi_header_op输出内容
char *content_type = "'Content-type: image/jpeg";
sapi_header_line ctr = {0};
ctr.line = content_type;
ctr.line_len = strlen(content_type);
ctr.response_code = 200;
sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); 

//2, 输出内容操作
//main/php_output.h

ZEND_BEGIN_MODULE_GLOBALS(output)
    int flags;              
    zend_stack handlers;
    php_output_handler *active;
    php_output_handler *running;
    const char *output_start_filename;
    int output_start_lineno;
ZEND_END_MODULE_GLOBALS(output)

#define PHP_OUTPUT_IMPLICITFLUSH        0x01
#define PHP_OUTPUT_DISABLED             0x02  //当flags=PHP_OUTPUT_DISABLED时,则会禁止输出
#define PHP_OUTPUT_WRITTEN              0x04
#define PHP_OUTPUT_SENT                 0x08
#define PHP_OUTPUT_ACTIVE               0x10
#define PHP_OUTPUT_LOCKED               0x20

#define PHP_OUTPUT_ACTIVATED        0x100000  
//当flags=PHP_OUTPUT_ACTIVATED,会调用sapi_module.ub_write输出, 每个SAPI都有自已的实现, cli中是调用sapi_cli_single_write()

php_output_write(); //输出,有buffer, 调用php_output_op()
php_output_write_unbuffered();//输出,没有buffer,调用PHP_OUTPUT_ACTIVATED,会调用sapi_module.ub_write
php_output_set_status(); //用于SAPI设置output.flags , 
php_output_get_status(); //获取output.flags的值

php_output_op();//

5,宏

#define PHPWRITE(str, str_len)      php_output_write((str), (str_len) TSRMLS_CC)
#define PHPWRITE_H(str, str_len)    php_output_write_unbuffered((str), (str_len) TSRMLS_CC)

#define PUTC(c)                     (php_output_write(&(c), 1 TSRMLS_CC), (c))
#define PUTC_H(c)                   (php_output_write_unbuffered(&(c), 1 TSRMLS_CC), (c))

#define PUTS(str)                   do {                \
    const char *__str = (str);                          \
    php_output_write(__str, strlen(__str) TSRMLS_CC);   \
} while (0)
#define PUTS_H(str)                 do {                            \
    const char *__str = (str);                                      \
    php_output_write_unbuffered(__str, strlen(__str) TSRMLS_CC);    \
} while (0)