| 191 | /** |
| 192 | * Removes a section between BEGIN and END markers in a file (.htaccess). |
| 193 | * |
| 194 | * Retains surrounding data. Creates file if none exists. |
| 195 | * |
| 196 | * @param string $filename Filename to alter. |
| 197 | * @param string $marker The marker to alter. |
| 198 | * @return bool True on write success, false on failure. |
| 199 | */ |
| 200 | function remove_with_markers( $filename, $marker ) { |
| 201 | if ( ! file_exists( $filename ) ) { |
| 202 | if ( ! is_writable( dirname( $filename ) ) ) { |
| 203 | return false; |
| 204 | } |
| 205 | } elseif ( ! is_writeable( $filename ) ) { |
| 206 | return false; |
| 207 | } |
| 208 | |
| 209 | $start_marker = "# BEGIN {$marker}"; |
| 210 | $end_marker = "# END {$marker}"; |
| 211 | |
| 212 | $fp = fopen( $filename, 'r+' ); |
| 213 | if ( ! $fp ) { |
| 214 | return false; |
| 215 | } |
| 216 | |
| 217 | // Attempt to get a lock. If the filesystem supports locking, this will block until the lock is acquired. |
| 218 | flock( $fp, LOCK_EX ); |
| 219 | |
| 220 | $lines = array(); |
| 221 | while ( ! feof( $fp ) ) { |
| 222 | $lines[] = rtrim( fgets( $fp ), "\r\n" ); |
| 223 | } |
| 224 | |
| 225 | // Split out the existing file into the preceding lines, and those that appear after the marker. |
| 226 | $pre_lines = $post_lines = array(); |
| 227 | $found_marker = $found_end_marker = false; |
| 228 | foreach ( $lines as $line ) { |
| 229 | if ( ! $found_marker && false !== strpos( $line, $start_marker ) ) { |
| 230 | $found_marker = true; |
| 231 | continue; |
| 232 | } elseif ( ! $found_end_marker && false !== strpos( $line, $end_marker ) ) { |
| 233 | $found_end_marker = true; |
| 234 | continue; |
| 235 | } |
| 236 | if ( ! $found_marker ) { |
| 237 | $pre_lines[] = $line; |
| 238 | } elseif ( $found_marker && $found_end_marker ) { |
| 239 | $post_lines[] = $line; |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | // Check if both markers were found. |
| 244 | if ( ! $found_marker || ! $found_end_marker ) { |
| 245 | flock( $fp, LOCK_UN ); |
| 246 | fclose( $fp ); |
| 247 | |
| 248 | return true; |
| 249 | } |
| 250 | |
| 251 | // Generate the new file data. |
| 252 | $new_file_data = implode( |
| 253 | "\n", |
| 254 | array_merge( |
| 255 | $pre_lines, |
| 256 | $post_lines |
| 257 | ) |
| 258 | ); |
| 259 | |
| 260 | // Write to the start of the file, and truncate it to that length. |
| 261 | fseek( $fp, 0 ); |
| 262 | $bytes = fwrite( $fp, $new_file_data ); |
| 263 | if ( $bytes ) { |
| 264 | ftruncate( $fp, ftell( $fp ) ); |
| 265 | } |
| 266 | fflush( $fp ); |
| 267 | flock( $fp, LOCK_UN ); |
| 268 | fclose( $fp ); |
| 269 | |
| 270 | return (bool) $bytes; |
| 271 | } |
| 272 | |