PHP preg_match unknown modifier error - codeigniter

Message: preg_match(): Unknown modifier 'p'
Filename: core/Router.php
Line Number: 399
Backtrace:
File: /home/spdcin/public_html/demo/no-waste/index.php
Line: 292
Function: require_once
iam getting this error on line 2
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
//line no 2
if (preg_match('#^'.$key.'$#', $uri, $matches))
{
// Are we using callbacks to process back-references?
if ( ! is_string($val) && is_callable($val))
{
// Remove the original string from the matches array.
array_shift($matches);
// Execute the callback using the values in matches as its parameters.
$val = call_user_func_array($val, $matches);
}
// Are we using the default routing method for back-references?
elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
{
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
$this->_set_request(explode('/', $val));
return;
}
}

There is a problem with your regex and PHP thinks you try to apply a 'p' modifier, which is not valid.
You will probably get to know what is wrong with your regex if you do :
echo '#^'.$key.'$#';
The fact that you try to program a router indicates that $key most probably contains '#p' (common in URLs).
Solution : In your case you can escape the character '#' with backslashes. Quoted from the php documentation :
"If the delimiter needs to be matched inside the pattern it must be escaped using a backslash."

If I understand your problem correctly, surround $key with preg_quote() like this:
if (preg_match('#^'.preg_quote($key).'$#', $uri, $matches))
This function will automatically escape ALL regex commands in $key.

Related

"Call to a member function format() on bool"

I need to convert a decimal number to a time. In pure php it works perfect, but when you put it in the Laravel controller, I get this error:
"Call to a member function format() on bool".
foreach($workdays as $hour){
$num1 = $hour->hours_work.'m';
$num_change1 = str_replace(',', 'h', $num1);
$hour->hours_work = DateTime::createFromFormat('H\h i\m', $num_change1)->format('H:i');
$num2 = $hour->hours_pause . 'm';
$num_change2 = str_replace(',', 'h', $num2);
$hour->hours_pause = DateTime::createFromFormat('H\h i\m', $num_change2)->format('H:i');
}
The entry would be 9.90
The departure should be 10:30
(This post has been translated via Google Translate)
If DateTime::createFromFormat produces an error, the return value will be false (boolean)

two regex tests within regex

now i have got a problem with preg_match.
This is an example string: "!asksheet!H69=var8949", there can also be more than one var8949 or H69 index in this row. Result shoud be "var33333=var8949"
This is my part:
preg_match_all('#\b\!(.*)\![A-Z]{1,3}\d+\b#', $output, $matches2);
foreach ($matches2[0] as $match2) {
$result6 = $db->query("SELECT varid FROM variablen WHERE varimportedindex = '".$match2."' AND projectid = $pid AND varsheetname LIKE '%".$match2."%' ");
$rowoperation2 = $result6->fetch_assoc();
if ($rowoperation2['varid'] != "" AND $rowoperation2['varid'] != "0") {
$output2 = preg_replace("#\b\!(.*)\![A-Z]{1,3}\d+\b#", "var".$rowoperation2['varid']."", $output);
}
}
Can someone perhaps help?
Thank you,
Regards
Olaf
Why not using a simple preg_match instead of preg_match_all, you don't need word boundary and exclamation mark doesn't need to be escaped, the strings you're looking for are in group 1 and 2:
$str = '"!asksheet!H69=var8949"';
preg_match('#!(.*?)!([A-Z]{1,3}\d+)#', $str, $m);
print_r($m);
Output:
Array
(
[0] => !asksheet!H69
[1] => asksheet
[2] => H69
)

Single quotes, double quotes and passwords containing $ in Windows and Unix

I'm writing a PHP script to automate a mysqldump command. The method I've selected is using exec( $exec_string . ' 2>&1' ). This script must work on Windows and *nix platforms.
Sadly, some passwords contain the dreaded $ symbol, and so the `-p'passwordcontaining$' must be quoted.
Here are the challenges I've noted so far:
On *nix, you must use the single quote, otherwise it will expand the
$ as a variable.
On Windows, you must use the double quote, because single quotes are treated literally
Escaping the $ is not an option, because on Windows the backslash is only interpreted as the escape character when preceding the double quote (\"), so \$ would be interpreted literally
I don't know how to reliably detect OS to be able to "interactively" switch between single and double quotes.
Is there a trick I am missing that will work cross-platform?
You can dump from within a pdo PHP script :
<?php
$dumpSettings = array(
'include-tables' => array('table1', 'table2'),
'exclude-tables' => array('table3', 'table4'),
'compress' => CompressMethod::GZIP, /* CompressMethod::[GZIP, BZIP2, NONE] */
'no-data' => false, /* http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_no-data */
'add-drop-table' => false, /* http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_add-drop-table */
'single-transaction' => true, /* http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_single-transaction */
'lock-tables' => false, /* http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_lock-tables */
'add-locks' => true, /* http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_add-locks */
'extended-insert' => true /* http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_extended-insert */
);
$dump = new MySQLDump('database','database_user','database_pass','localhost', $dumpSettings);
$dump->start('forum_dump.sql.gz');
See https://github.com/clouddueling/mysqldump-php
Not crazy about the approach I ended up adopting (MySQLDump class seems to be a more robust approach than exec() ), but here it is in case it helps anyone.
Even though I didn't want to do OS detection, at first blush it doesn't seem that I can resolve the issues in quote interpretation. Happily, OS detection is relatively easy, if you're prepared to make some assumptions, such as "if it ain't running on Windows, then it's on some kind of *nix server".
Here's my basic approach, which I'm sure will get flamed.
// Inside class
protected $os_quote_char = "'"; // Unix default quote character
// Inside constructor
// Detect OS and set quote character appropriately
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
$this->os_quote_char = '"';
// Method for adding quotes
/**
* Adds the OS non-interpreted quote character to the string(s), provided each string doesn't already start with said quote character.
*
* The quote character is set in the constructor, based on detecting Windows OSes vs. any other (assumed to be *nix).
* You can pass in an array, in which case you will get an array of quoted strings in return.
*
* #param string|array $string_or_array
* #return string|array
*/
protected function os_quote( $string_or_array ){
$quoted_strings = array();
$string_array = (array) $string_or_array;
foreach ( $string_array as $string_to_quote ){
// don't quote already quoted strings
if ( substr( $string_to_quote, 0, 1 ) == $this->os_quote_char )
$quoted_strings[] = $string_to_quote;
else
$quoted_strings[] = $this->os_quote_char . $string_to_quote . $this->os_quote_char;
}
if ( is_array( $string_or_array ) )
return $quoted_strings;
else
return $quoted_strings[0];
}
// Actual usage example:
if ( function_exists( 'exec' ) ){
list( $user, $pwd, $host, $db, $file ) = $this->os_quote( array( DB_USER, DB_PASSWORD, DB_HOST, DB_NAME, $backup_file.'.sql' ) );
$exec = $this->get_executable_path() . 'mysqldump -u' . $user . ' -p' . $pwd . ' -h' . $host . ' --result-file=' . $file . ' ' . $db . ' 2>&1';
exec ( $exec, $output, $return );
}
It's hard to guess, what limitations you are talking about, but I suspect some of them are false
passthru('mysqldump -uddd -p"pass\'word$" ddd');
Worked for me under Windows and FreeBSD, as well as the command itself in the respective shells

Scraping multiple items off of a Page into a Neat Row

As an example:
I load in the input from a .txt:
Benjamin,Schuvlein,Germany,1912,M,White
I do some code that I will not post here for brevity and get to the link:
https://familysearch.org/pal:/MM9.1.1/K3BN-LLJ
I want to scrape multiple things from that page. In the code below, I only do 1.
I'd also like to make each item be separated by a , in the output .txt.
And, I'd like the output to be preceded by the input.
I'm using the following packages in the code:
use strict;
use warnings;
use WWW::Mechanize::Firefox;
use Data::Dumper;
use LWP::UserAgent;
use JSON;
use CGI qw/escape/;
use HTML::DOM;
Here's the relevant code:
my $ua = LWP::UserAgent->new;
open(my $o, '>', 'out2.txt') or die "Can't open output file: $!";
# Here is the url, although in practice, it is scraped itself using different code
my $url = 'https://familysearch.org/pal:/MM9.1.1/K3BN-LLJ';
print "My URL is <$url>\n";
my $request = HTTP::Request->new(GET => $url);
$request->push_header('Content-Type' => 'application/json');
my $response = $ua->request($request);
die "Error ".$response->code if !$response->is_success;
my $dom_tree = new HTML::DOM;
$dom_tree->write($response->content);
$dom_tree->close;
my $str = $dom_tree->getElementsByTagName('table')->[0]->getElementsByTagName("td")->[10]->as_text();
print $str;
print $o $str;
Desired Output (from that link) is something like:
Benjamin,Schuvlein,Germany,1912,M,White,Queens,New York,Married,Same Place,Head, etc ....
(How much of that output section is scrapable?)
Any help on how to get the link within the link would be much appreciated!
This is fairly simply done using HTML::TreeBuilder::XPath to access the HTML. This program builds a hash of the data using the labels as keys, so any of the desired information can be extracted. I have enclosed in quotes any fields that contain commas or whitespace.
I don't know whether you have the permission of this web site to extract data this way, but I should draw your attention to this X-Copyright header in the HTTP responses. This approach clearly falls under the header of programmatic access.
X-Copyright: COPYRIGHT WARNING Data accessible through the FamilySearch API is protected by copyright. Any programmatic access, reformatting, or rerouting of this data, without permission, is prohibited. FamilySearch considers such unauthorized use a violation of its reproduction, derivation, and distribution rights. Contact devnet (at) familysearch.org for further information.
Am I to expect an email from you? I replied to your first mail but haven't heard since.
use strict;
use warnings;
use URI;
use LWP;
use HTML::TreeBuilder::XPath;
my $url = URI->new('https://familysearch.org/pal:/MM9.1.1/K3BN-LLJ');
my $ua = LWP::UserAgent->new;
my $resp = $ua->get($url);
die $resp->status_line unless $resp->is_success;
my $tree = HTML::TreeBuilder::XPath->new_from_content($resp->decoded_content);
my #results = $tree->findnodes('//table[#class="result-data"]//tr[#class="result-item"]');
my %data;
for my $item (#results) {
my ($key, $val) = map $_->as_trimmed_text, $item->content_list;
$key =~ s/:$//;
$data{$key} = $val;
}
my $record = join ',', map { local $_ = $data{$_}; /[,\s]/ ? qq<"$_"> : $_ }
'name', 'birthplace', 'estimated birth year', 'gender', 'race (standardized)',
'event place', 'marital status', 'residence in 1935',
'relationship to head of household (standardized)';
print $record, "\n";
output
"Benjamin Schuvlein",Germany,1912,Male,White,"Assembly District 2, Queens, New York City, Queens, New York, United States",Married,"Same Place",Head
Try this
use LWP::Simple;
use LWP::UserAgent;
use HTML::TableExtract;
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
$ua = LWP::UserAgent->new;
$ua->agent("Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.91 Safari/537.11");
$req = HTTP::Request->new(GET => "https://familysearch.org/pal:/MM9.1.1/K3BN-LLJ");
$res = $ua->request($req);
$content = $res->content;
#$content = get("https://familysearch.org/pal:/MM9.1.1/K3BN-LLJ") or die "Couldn't get it! $!";
$te = HTML::TableExtract->new( attribs => { 'class' => 'result-data' } );
# $te = HTML::TableExtract->new( );
$te->parse($content);
$table = $te->first_table_found;
# print $content; exit;
# $te->tables_dump(1);
#print Dumper($te);
#print Dumper($table);
print $table->cell(4,0) . ' = ' . $table->cell(4,1), "\n"; exit;
Which prints out
event place: = Assembly District 2, Queens, New York City, Queens, New York, United States
I also noticed this header:
X-Copyright:COPYRIGHT WARNING Data accessible through the FamilySearch API is protected by copyright. Any programmatic access, reformatting, or rerouting of this data, without permission, is prohibited. FamilySearch considers such unauthorized use a violation of its reproduction, derivation, and distribution rights. Contact devnet (at) familysearch.org for further information.
See also http://metacpan.org/pod/HTML::Element#SYNOPSIS
I thought I had answered your question.
The problem is that you are trying to fetch the webpage with LWP. Why are try to doing that if you already have WWW::Mechanize::Firefox?
Did you tried this?
It will retrieve and save each link for further analyses. A small change and you 'get' the DOM tree. Sorry, I do not have acccess to this page, so I just hope it will work.
my $i=1;
for my $link (#links) {
print Dumper $link->url;
print Dumper $link->text;
my $tempfile = './$i.html';$i++;
$mech->get( $link, ':content_file' => $tempfile, synchronize => 1 );
my $dom_tree = $mech->document();
my $str = $dom_tree->getElementsByTagName('table')->[0]->getElementsByTagName("td")->[9]->as_text();
}
EDIT:
Process the page content with regexp (Everyone: Please remember, there is always more than one way to do something wwith Perl!. It works, it is easy...)
it tried it out with this cmd:
wget -nd 'https://familysearch.org/pal:/MM9.1.1/K3BN-LLJ' -O 1.html|cat 1.html|1.pl
use Data::Dumper;
use strict;
use warnings;
local $/=undef;
my $html = <>;#read from file
#$html = $mech->content( format => 'html' );# read data from mech object
my $data = {};
my $current_label = "not_defined";
while ($html =~ s!(<td[^>]*>.*?</td>)!!is){ # process each TD
my $td = $1;
print "td: $td\n";
my $td_val = $td;
$td_val =~ s!<[^>]*>!!gis;
$td_val =~ s!\s+! !gs;
$td_val =~ s!(\A\s+|\s+\z)!!gs;
if ($td =~ m!result-label!){ #primitive state machine, store the current label
print "current_label: $current_label\n";
$current_label = $td_val;
} elsif ($td =~ m!result-value!){ #add each data to current label
push(#{$data->{$current_label}},$td_val);
} else {
warn "found something else: $td\n";
}
}
#process it using a white lists of known entries (son,race, etc).Delete from the result if you find it on white list, die if you find something new.
#multi type
foreach my $type (qw(son wife daughter head)){
process_multi($type,$data->{$type});
delete($data->{$type});
}
#simple type
foreach my $type (qw(birthplace age)){
process_simple($type,$data->{$type});
delete($data->{$type});
}
die "Unknown label!".Dumper($data) if scalar(keys %{$data})>0;
Output:
'line number:' => [
'28'
],
'estimated birth year:' => [
'1912'
],
'head' => [
'Benjamin Schuvlein',
'M',
'28',
'Germany'
],

Joomla 1.5 Call for get_path('admin_html') returning Null

On line 18 of the admin.categories.php file there is
require_once( JApplicationHelper::getPath( 'admin_html' ) );
The Helper Library file has not been modified, it still reads
function getPath( $varname, $user_option=null )
$check = ( ( $varname == 'mod0_xml' ) || ( $varname == 'mod1_xml' ) );
if ( !$user_option && !$check ) {
$user_option = JRequest::getCmd('option');
} else {
$user_option = JFilterInput::clean($user_option, 'path');
}
$result = null;
$name = substr( $user_option, 4 );
...
case 'admin_html':
$path = DS.'components'.DS. $user_option .DS.'admin.'. $name .'.html.php';
$result = JApplicationHelper::_checkPath( $path, -1 );
break;
So it's going to wind up building a path '/components//admin..html.php' because the $name and $user_option variables are both empty, right? Then the checkpath fails, which returns null during a failure. None of this code has been modified to my knowledge. So what gives? Anyone point me in the right direction?
The problem this causes is that it throws a fatal error when it can't open a required file. So I can't open the category manager.
So when you select Category Manager from the Content menu getPath() is called with $varname == 'admin_html' and $user_option == null.
That means that as the first if() is true (because null equates to false and $check is false) $user_option gets set to com_categories (the result of the JRequest::getCmd('option'); line)
Then $name gets set to 'categories', so when the switch() get to the admin_html case it is setting $path to /components/com_categories/admin.categories.html.php (assuming the local directory separator is set to / ).
So as that is the right path and that file is normally included on a J1.5 installation something else has gone wrong (or the file has been removed/deleted)

Resources