"Fossies" - the Fresh Open Source Software Archive

Member "mod_ftp-0.9.6/modules/ftp/ftp_filters.c" (28 May 2009, 4972 Bytes) of package /linux/www/apache_httpd_modules/old/mod_ftp-0.9.6-beta.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ftp_filters.c" see the Fossies "Dox" file reference documentation.

    1 /* Licensed to the Apache Software Foundation (ASF) under one or more
    2  * contributor license agreements.  See the NOTICE file distributed with
    3  * this work for additional information regarding copyright ownership.
    4  * The ASF licenses this file to You under the Apache License, Version 2.0
    5  * (the "License"); you may not use this file except in compliance with
    6  * the License.  You may obtain a copy of the License at
    7  *
    8  *     http://www.apache.org/licenses/LICENSE-2.0
    9  *
   10  * Unless required by applicable law or agreed to in writing, software
   11  * distributed under the License is distributed on an "AS IS" BASIS,
   12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13  * See the License for the specific language governing permissions and
   14  * limitations under the License.
   15  */
   16 
   17 /*
   18  * Original Copyright (c) 2005 Covalent Technologies
   19  *
   20  * FTP Protocol module for Apache 2.0
   21  */
   22 
   23 #include "mod_ftp.h"
   24 #include "ftp_internal.h"
   25 
   26 /* ftp_crlf_filter: Filter for sending ASCII files.  RFC 959 states that
   27  *                  CRLF should be use where necessary to denote the end
   28  *                  of line.  This filter replaces all LF's with CRLF's.
   29  *
   30  *                  I believe most clients strip the CR's anyway, but we
   31  *                  need them to transfer the file properly.
   32  *
   33  * Arguments: f - The current filter.
   34  *            bb - The bucket brigade sent down the filter stack.
   35  *
   36  * Returns:  APR_SUCCESS on success, otherwise the status code is returned.
   37  */
   38 
   39 apr_status_t ftp_crlf_filter(ap_filter_t *f, apr_bucket_brigade *bb)
   40 {
   41     apr_bucket *e;
   42     apr_bucket *b;
   43     apr_status_t rv;
   44     apr_off_t this_size = 0;
   45     int *seen_cr = (int *) f->ctx;
   46 
   47     e = APR_BRIGADE_FIRST(bb);
   48     while (e != APR_BRIGADE_SENTINEL(bb)) {
   49         const char *buf;
   50         apr_size_t len;
   51         const char *pos;
   52 
   53         if (e->length == 0) {
   54             e = APR_BUCKET_NEXT(e);     /* onwards */
   55             continue;
   56         }
   57 
   58         rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
   59         if (rv != APR_SUCCESS) {
   60             return rv;
   61         }
   62 
   63         /*
   64          * Skip all of the extra effort below for empty buckets, if this is
   65          * EOS we will catch it at the while condition looking for the
   66          * trailing sentinal.
   67          */
   68         if (len == 0) {
   69             e = APR_BUCKET_NEXT(e);     /* onwards */
   70             continue;
   71         }
   72 
   73         /* Handle case where we have a leading LF */
   74         if (!*seen_cr) {
   75             if (buf[0] == '\n') {
   76                 b = apr_bucket_immortal_create("\r", 1,
   77                                                f->c->bucket_alloc);
   78                 APR_BUCKET_INSERT_BEFORE(e, b);
   79                 this_size += 1;
   80             }
   81         }
   82         else {
   83             *seen_cr = 0;
   84         }
   85 
   86         /*
   87          * We search the data for a LF without a preceeding CR. If we find
   88          * one, we split the bucket so that the LF is the first character in
   89          * the new bucket, and then insert a new bucket with a CR and insert
   90          * it before the LF bucket (ignored on the next loop by seen_cr.) As
   91          * long as we keep seeing CRLF pairs, keep looking forward through
   92          * the buffer.
   93          */
   94         pos = buf;
   95         while (++pos, pos = memchr(pos, APR_ASCII_LF, len - (pos - buf))) {
   96             /*
   97              * We found a bare linefeed, insert a CR and advance to the
   98              * LF-remainder (we skip that LF above)
   99              */
  100             if (*(pos - 1) != APR_ASCII_CR) {
  101                 apr_bucket_split(e, pos - buf);
  102                 e = APR_BUCKET_NEXT(e); /* second half */
  103                 b = apr_bucket_immortal_create("\r", 1,
  104                                                f->c->bucket_alloc);
  105                 APR_BUCKET_INSERT_BEFORE(e, b);
  106                 this_size += (pos - buf) + 1;   /* including the CR */
  107                 *seen_cr = 1;
  108                 break;
  109             }
  110         }
  111 
  112         /*
  113          * If we just split, we will 'reread' this current bucket... But
  114          * otherwise we note if the trailing character is a CR, tally this
  115          * bucket, and advance to the next bucket
  116          */
  117         if (!pos) {
  118             *seen_cr = (buf[len - 1] == '\r');
  119             this_size += len;
  120             e = APR_BUCKET_NEXT(e);     /* onwards */
  121         }
  122 
  123         /*
  124          * We got too big and chunky, let's spill this out to the client data
  125          * connection and resume processing
  126          */
  127         if (this_size >= 9000) {
  128             apr_bucket_brigade *bb_split = bb;
  129             bb = apr_brigade_split(bb_split, e);
  130             rv = ap_pass_brigade(f->next, bb_split);
  131             if (rv != APR_SUCCESS)
  132                 return rv;
  133             this_size = 0;
  134         }
  135     }
  136 
  137     if (APR_BRIGADE_EMPTY(bb))
  138         rv = APR_SUCCESS;
  139     else {
  140         rv = ap_pass_brigade(f->next, bb);
  141         if (rv == APR_SUCCESS && f->c->aborted)
  142             rv = AP_FILTER_ERROR;
  143     }
  144     return rv;
  145 }