I have a file name examples:
4030-2210201884140.jpg
527884197_w640_h640_1ff2cccdbed562cef696d0c7adf41292.jpg
need to do to so was:
4030-22...1884140.jpg
5278841...df41292.jpg
Been looking for a solution but could not find it.
I have visited the post
Cutting down a length of a PHP string and inserting an ellipses
But sometimes it may not fit for you try below function
I have converted your requirement to a function with default arguments:
function getFirstLast($string='527884197_w640_h640_1ff2cccdbed562cef696d0c7adf41292.jpg',$orgOnF=7,$orgOnB=-11,$maskedString='.',$maskRepeat=3)
{
if (strlen($string) <= 21)
{
return $string;
}
$firstPartString = mb_substr($string, 0 ,$orgOnF);
$secondPartString = mb_substr($string,$orgOnB);
$maskedString = str_repeat($maskedString, $maskRepeat);
$finalResult = $firstPartString.$maskedString.$secondPartString;
return $finalResult;
}
echo getFirstLast();
Related
I have a legacy classic asp application, that allows us to upload pdf files. The file is saved as hex into a MS SQL DB into an image column. Here is a snip of the data in the column:
0x4A564245526930784C6A634E436957317462573144516F784944416762324A7144516F...
We are now working on a rework of the app using node.js as our backend and angular4 as the front end. As part of that, we need to be able to download the same file in the new app. If I upload the same file using angular4 then the image data looks like this:
0x255044462D312E370D0A25B5B5B5B50D0A312030206F626A0D0A3C3C2F547970652F43...
As you can see the hex is completely different and I am not sure what is causing this. I have tried to look at the classic asp code, but its very old and there is no special encoding or such that is happening that would cause this.
In Angular4 we are using the standard input type file control with the change event to capture the contents of the file and then saving it into our db:
myReader.onloadend = (f) => {
let image64;
if (myReader.result.toString()) {
let base64id = ';base64,';
image64 = myReader.result.substr(myReader.result.indexOf(base64id) + base64id.length);
}
someService.upload(image64);
}
So nothing crazy going on, right? The problem now is that I am able to download the file uploaded via angular fine, but not the ones that were uploaded via classic asp. I receive the following error when I try:
Failed to execute 'atob' on 'Window': The string to be decoded is not
correctly encoded.
Here is the code used to upload the files via classic ASP:
Public Function Load()
Dim PosBeg, PosEnd, PosFile, PosBound, boundary, boundaryPos, Pos
Dim Name, Value, FileName, ContentType
Dim UploadControl
PosBeg = 1
PosEnd = InstrB(PosBeg,m_FormRawData,getByteString(chr(13)))
boundary = MidB(m_FormRawData,PosBeg,PosEnd-PosBeg)
boundaryPos = InstrB(1,m_FormRawData,boundary)
'Get all data inside the boundaries
Do until (boundaryPos=InstrB(m_FormRawData,boundary & getByteString("--")))
Set UploadControl = Server.CreateObject("Scripting.Dictionary")
Pos = InstrB(BoundaryPos,m_FormRawData,getByteString("Content-Disposition"))
Pos = InstrB(Pos,m_FormRawData,getByteString("name="))
PosBeg = Pos+6
PosEnd = InstrB(PosBeg,m_FormRawData,getByteString(chr(34)))
Name = getString(MidB(m_FormRawData,PosBeg,PosEnd-PosBeg))
PosFile = InstrB(BoundaryPos,m_FormRawData,getByteString("filename="))
PosBound = InstrB(PosEnd,m_FormRawData,boundary)
If PosFile<>0 AND (PosFile<PosBound) Then
PosBeg = PosFile + 10
PosEnd = InstrB(PosBeg,m_FormRawData,getByteString(chr(34)))
FileName = getString(MidB(m_FormRawData,PosBeg,PosEnd-PosBeg))
UploadControl.Add "FileName", FileName
Pos = InstrB(PosEnd,m_FormRawData,getByteString("Content-Type:"))
PosBeg = Pos+14
PosEnd = InstrB(PosBeg,m_FormRawData,getByteString(chr(13)))
ContentType = getString(MidB(m_FormRawData,PosBeg,PosEnd-PosBeg))
UploadControl.Add "ContentType",ContentType
PosBeg = PosEnd+4
PosEnd = InstrB(PosBeg,m_FormRawData,boundary)-2
Value = MidB(m_FormRawData,PosBeg,PosEnd-PosBeg)
UploadControl.Add "value" , Value
m_dicFileData.Add LCase(name), UploadControl
Else
Pos = InstrB(Pos,m_FormRawData,getByteString(chr(13)))
PosBeg = Pos+4
PosEnd = InstrB(PosBeg,m_FormRawData,boundary)-2
Value = getString(MidB(m_FormRawData,PosBeg,PosEnd-PosBeg))
UploadControl.Add "value" , Value
End If
m_dicForm.Add LCase(name), UploadControl
BoundaryPos=InstrB(BoundaryPos+LenB(boundary),m_FormRawData,boundary)
Loop
Load = m_blnSucceed
End Function
Any idea what I can do here to fix this? I need to be able to download the old files as well. Is there an encoding or something else I am missing here?
After further looking into this, it seems the following is causing the error: Node.js will send a buffer to the front-end. On the front-end I then convert the buffer into base64 using the below code:
_arrayBufferToBase64(buffer) {
let base64 = '';
let bytes = new Uint8Array(buffer);
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
bbase64 += String.fromCharCode(bytes[i]);
}
return base64;
}
The returned base64 from the old classic asp is returned as garbage and looks like this:
*R{£ÌõGpÃì#j¾é>i¿ê A l Ä ð!!H!u!¡!Î!û"'"U""¯"Ý#
(?(q(¢(Ô))8)k))Ð5*hÏ++6+i++Ñ,,9,n,¢,×-''I'z'«'Ü(
3F33¸3ñ4+4e44Ø55M55Â5ý676r6®6é7$7`77×88P88È99B99¼9ù:6:t
I am still not sure how to fix this though.
I have a closure working properly on traverse, but another of the same kind is failing. I'm suspecting scope or timing is causing this to fail. The working code sums the size of files in the file system. The code not working is inspecting the content of the file and only prints one match. Running these with Grails 2.3.7
working code:
def groovySrcDir = new File('.', 'plugins/')
def countSmallFiles = 0
def postDirVisitor = {
if (countSmallFiles > 0) {
println "Found $countSmallFiles files with small filenames in ${it.name}"
}
countSmallFiles = 0
}
groovySrcDir.traverse(type: FILES, postDir: postDirVisitor, nameFilter: ~/.*\.groovy$/) {
if (it.name.size() < 15) {
countSmallFiles++
}
}
problem code:
def datamap = [:]
def printDomainFound = {
//File currentFile = new File(it.canonicalPath)
def fileText = it.text
if(fileText.indexOf("#Table ") > 0){
//println "Found a Table annotation in ${it.name} "
datamap.put(it.name, it.name)
}
}
groovySrcDir.traverse type: FILES, visit: printDomainFound, nameFilter: filterGroovyFiles
datamap.each {
println it.key
}
I tested your code and worked fine.
Which behaviour are you expecting?
I find a couple of suspicious things:
If fileText begins with "#Table " then indexOf will return 0 and the condition if(fileText.indexOf("#Table ") > 0) will not be satisfied.
"#Table " has a trailing space, then a file containing, for example: "#Table(", will not be printed.
You can also check that filterGroovyFiles has the appropiate value.
I hope it'll help.
-- EDIT --
Running the code with def filterGroovyFiles = ~/.*\.groovy$/ and this file tree:
plugins
|--sub1
| |-dum.groovy
| |-dum2.groovy
dum3.groovy
And all three groovy files containing the (but not starting with!!) "#Table " (with trailing space!!). I get the expected output:
dum3.groovy
dum.groovy
dum2.groovy
(Note both dum.groovy and dum2.groovy from the same folder sub1 are appearing).
I'm using groovy 2.0.5.
Please recheck your files :
Have the correct extension
Contain but not at the begining (index==0) the String "#Table "
Can Matlab eliminate the path in URL and leave only the domain part? Does Matlab have any function to eliminate the path behind?
Let's say, example 1:
input :http://www.mathworks.com/help/images/removing-noise-from-images.html
output :http://www.mathworks.com
This regexp pattern should do the trick:
>> str = 'http://www.mathworks.com/help/images/removing-noise-from-images.html';
>> out = regexp(str,'\w*://[^/]*','match','once')
out =
'http://www.mathworks.com'
The search pattern '\w*://[^/]*' says look for a string that starts with some "word" characters ('\w*) corresponding to the protocol (e.g. http, https, rtsp), followed by the ubiquitous ://, and then any number of characters that are not a forward slash ([^/]*).
Edit: The 'once' option should eliminate a nested cell.
UPDATE: just the hostname, allowing inputs with no protocol.
>> str = {'http://www.mathworks.com/help/images/removing-noise-from-images.html';
'https://www.mathworks.com/help/matlab/ref/strcmpi#dfvfv.html';
'google.com/voice'}
>> out = regexp(str,'([^/]*)(?=/[^/])','match','once')
out =
'www.mathworks.com'
'www.mathworks.com'
'google.com'
UPDATE 2: regexp madness!
>> str = {'http://www.mathworks.com/help/images/removing-noise-from-images.html';
'https://www.mathworks.com/help/matlab/ref/strcmpi#dfvfv.html';
'google.com/voice';
'http://monkey.org/';
'stackoverflow.com/';
'meta.stackoverflow.com'};
>> out = regexp(str,'.*?[^/](?=(/([^/]|$)|$))','match','once')
out =
'http://www.mathworks.com'
'https://www.mathworks.com'
'google.com'
'http://monkey.org'
'stackoverflow.com'
'meta.stackoverflow.com'
% hostname.m
function hostnames = hostname(str)
hostnames = regexp(str,'.*?[^/](?=(/([^/]|$)|$))','match','once');
Code:
function output_url = domain_name(input_url)
c1 = strfind(input_url,'//');
ind1 = strfind(input_url,'/');
if isempty(c1) && isempty(ind1)
output_url = input_url; % For case like - www.mathworks.com
return;
end
if ~isempty(c1)
if numel(ind1)>2
output_url = input_url(1:ind1(3)-1); % For cases like - http://www.mathworks.com/ or http://www.mathworks.com/something/
else
output_url = input_url; % For case like - http://www.mathworks.com
end
else
output_url = input_url(1:ind1(1)-1); % For cases like - www.mathworks.com/ or www.mathworks.com/something/
end
return;
Example runs:
%% Long URLs with extensions
disp(domain_name('www.mathworks.com/help/images/removing-noise-from-images.html'))
disp(domain_name('http://www.mathworks.com/help/images/removing-noise-from-images.html'))
%% Short URLs without HTTP://
disp(domain_name('www.mathworks.com'))
disp(domain_name('www.mathworks.com/'))
%% Short URLs with HTTP://
disp(domain_name('http://www.mathworks.com'))
disp(domain_name('http://www.mathworks.com/'))
Return:
www.mathworks.com
http://www.mathworks.com
www.mathworks.com
www.mathworks.com
http://www.mathworks.com
http://www.mathworks.com
An alternative method and probably efficient one would be to use REGEXP, but apparently I prefer numbers.
Edit 1: If you prefer to use bunch of URLs at the sametime, you may use a cell array. Obviously, the output would be a cell array too. Look at the following MATLAB script to get a feel of it -
% Input
in_urls_cell = [{'http://mathworks.com/'},{'mathworks.com/help/matlab/ref/strcmpi.html'},{'mathworks.com/help/matlab/ref/strcmpi#dfvfv.html'}];
% Get domain name
out_urls_cell = cell(size(in_urls_cell));
for count = 1:numel(in_urls_cell)
out_urls_cell(count)={domain_name(cell2mat(in_urls_cell(count)))};
end
% Display only domain name
for count = 1:numel(out_urls_cell)
disp(cell2mat(out_urls_cell(count)));
end
The above script returns -
http://mathworks.com
mathworks.com
mathworks.com
SOLVED ALREADY --> See edit 7
At this moment I'm fairly new on Perl, and trying to modify part of an existing page (in Wonderdesk).
The way the page works, is that it gets the information from the GET url and parses it to an SQL query.
Since this is part of a much larger system, I'm not able to modify the coding around it, and have to solve it in this script.
A working test I performed:
$input->{help_id} = ['33450','31976'];
When running this, the query that is being build returns something as
select * from table where help_id in(33450,31976)
The part of my code that does not work as expected:
my $callIDs = '33450,31450';
my #callIDs = split(/,/,$callIDs);
my $callIDsearch = \#callIDs;
$input->{help_id} = $callIDsearch;
When running this, the query that is being build returns something as
select * from table where help_id = '33450,31976'
I've tried to debug it, and used Data::Dumper to get the result of $callIDsearch, which appears as [33450, 31450] in my browser.
Can someone give me a hint on how to transform from '123,456' into ['123', '456']?
With kind regards,
Marcel
--===--
Edit:
As requested, minimal code piece that works:
$input->{help_id} = ['123','456']
Code that does not work:
$str = '123,456';
#ids = split(/,/,$str);
$input->{help_id} = \#ids;
--===--
Edit 2:
Source of the question:
The following part of the code is responsible for getting the correct information from the database:
my $input = $IN->get_hash;
my $db = $DB->table('help_desk');
foreach (keys %$input){
if (/^corr/ and !/-opt$/ and $input->{$_} or $input->{keyword}){
$db = $DB->table('help_desk','correspondence');
$input->{rs} = 'DISTINCT help_id,help_name,help_email,help_datetime,help_subject,help_website,help_category,
help_priority,help_status,help_emergency_flag,help_cus_id_fk,help_tech,help_attach';
$input->{left_join} = 1;
last;
}
}
# Do the search
my $sth = $db->query_sth($input);
my $hits = $db->hits;
Now instead of being able to provide a single parameter help_id, I want to be able to provide multiple parameters.
--===--
Edit 3:
query_sth is either of the following two, have not been able to find it out yet:
$COMPILE{query} = __LINE__ . <<'END_OF_SUB';
sub query {
# -----------------------------------------------------------
# $obj->query($HASH or $CGI);
# ----------------------------
# Performs a query based on the options in the hash.
# $HASH can be a hash ref, hash or CGI object.
#
# Returns the result of a query as fetchall_arrayref.
#
my $self = shift;
my $sth = $self->_query(#_) or return;
return $sth->fetchall_arrayref;
}
END_OF_SUB
$COMPILE{query_sth} = __LINE__ . <<'END_OF_SUB';
sub query_sth {
# -----------------------------------------------------------
# $obj->query_sth($HASH or $CGI);
# --------------------------------
# Same as query but returns the sth object.
#
shift->_query(#_)
}
END_OF_SUB
Or
$COMPILE{query} = __LINE__ . <<'END_OF_SUB';
sub query {
# -------------------------------------------------------------------
# Just performs the query and returns a fetchall.
#
return shift->_query(#_)->fetchall_arrayref;
}
END_OF_SUB
$COMPILE{query_sth} = __LINE__ . <<'END_OF_SUB';
sub query_sth {
# -------------------------------------------------------------------
# Just performs the query and returns an active sth.
#
return shift->_query(#_);
}
END_OF_SUB
--===--
Edit 4: _query
$COMPILE{_query} = __LINE__ . <<'END_OF_SUB';
sub _query {
# -------------------------------------------------------------------
# Parses the input, and runs a select based on input.
#
my $self = shift;
my $opts = $self->common_param(#_) or return $self->fatal(BADARGS => 'Usage: $obj->insert(HASH or HASH_REF or CGI) only.');
$self->name or return $self->fatal('NOTABLE');
# Clear errors.
$self->{_error} = [];
# Strip out values that are empty or blank (as query is generally derived from
# cgi input).
my %input = map { $_ => $opts->{$_} } grep { defined $opts->{$_} and $opts->{$_} !~ /^\s*$/ } keys %$opts;
$opts = \%input;
# If build_query_cond returns a GT::SQL::Search object, then we are done.
my $cond = $self->build_query_cond($opts, $self->{schema}->{cols});
if ( ( ref $cond ) =~ /(?:DBI::st|::STH)$/i ) {
return $cond;
}
# If we have a callback, then we get all the results as a hash, send them
# to the callback, and then do the regular query on the remaining set.
if (defined $opts->{callback} and (ref $opts->{callback} eq 'CODE')) {
my $pk = $self->{schema}->{pk}->[0];
my $sth = $self->select($pk, $cond) or return;
my %res = map { $_ => 1 } $sth->fetchall_list;
my $new_results = $opts->{callback}->($self, \%res);
$cond = GT::SQL::Condition->new($pk, 'IN', [keys %$new_results]);
}
# Set the limit clause, defaults to 25, set to -1 for none.
my $in = $self->_get_search_opts($opts);
my $offset = ($in->{nh} - 1) * $in->{mh};
$self->select_options("ORDER BY $in->{sb} $in->{so}") if ($in->{sb});
$self->select_options("LIMIT $in->{mh} OFFSET $offset") unless $in->{mh} == -1;
# Now do the select.
my #sel = ();
if ($cond) { push #sel, $cond }
if ($opts->{rs} and $cond) { push #sel, $opts->{rs} }
my $sth = $self->select(#sel) or return;
return $sth;
}
END_OF_SUB
--===--
Edit 5: I've uploaded the SQL module that is used:
https://www.dropbox.com/s/yz0bq8ch8kdgyl6/SQL.zip
--===--
Edit 6:
On request, the dumps (trimmed to only include the sections for help_id):
The result of the modification in Base.pm for the non-working code:
$VAR1 = [
33450,
31450
];
The result of the modification in Condition.pm for the non-working code:
$VAR1 = [
"help_id",
"IN",
[
33450,
31450
]
];
$VAR1 = [
"cus_username",
"=",
"Someone"
];
$VAR1 = [
"help_id",
"=",
"33450,31450"
];
The result for the modification in Base.pm for the working code:
$VAR1 = [
33450,
31976
];
The result for the modification in Condition.pm for the working code:
$VAR1 = [
"help_id",
"IN",
[
33450,
31976
]
];
It looks as if the value gets changed afterwards somehow :S
All I changed for the working/non-working code was to replace:
$input->{help_id} = ['33450','31976'];
With:
$input->{help_id} = [ split(/,/,'33450,31450') ];
--===--
Edit 7:
After reading all the tips, I decided to start over and found that by writing some logs to files, I could break down into the issue with more details.
I'm still not sure why, but it now works, using the same methods as before. I think it's a typo/glitch/bug in my code somewhere..
Sorry to have bothered you all, but I still recommend the points to go to amon due to his tips providing the breakthrough.
I don't have an answer, but I have found a few critical points where we need to know what is going on.
In build_query_cond (Base.pm line 528), an array argument will be transformed into an key in (...) relation:
if (ref($opts->{$field}) eq 'ARRAY' ) {
my $add = [];
for ( #{$opts->{$field}} ) {
next if !defined( $_ ) or !length( $_ ) or !/\S/;
push #$add, $_;
}
if ( #$add ) {
push #ins, [$field, 'IN', $add];
}
}
Interesting bit in sql (Condition.pm line 181). Even if there is an arrayref, an IN test will be simplified to an = test if it contains only a single element.
if (uc $op eq 'IN' || $op eq '=' and ref $val eq 'ARRAY') {
if (#$val > 1) {
$op = 'IN';
$val = '('
. join(',' => map !length || /\D/ ? quote($_) : $_, #$val)
. ')';
}
elsif (#$val == 0) {
($col, $op, $val) = (qw(1 = 0));
}
else {
$op = '=';
$val = quote($val->[0]);
}
push #output, "$col $op $val";
}
Before these two conditions, it would be interesting to insert the following code:
Carp::cluck(Data::Dumper::Dump(...));
where ... is $opts->{$field} in the first snippet or $cond in the second snippet. The resulting stack trace would allow us to find all subroutines which could have modified the value. For this to work, the following code has to be placed in your main script before starting the query:
use Carp ();
use Data::Dumper;
$Data::Dumper::Useqq = 1; # escape special characters
Once the code has been modified like this, run both the working and not-working code, and print out the resulting query with
print Dumper($result);
So for each of your code snippets, we should get two stack traces and one resulting SQL query.
A shot in the dark... there's a temporary array #callIDs created by this code:
my #callIDs = split(/,/,$callIDs);
my $callIDsearch = \#callIDs;
$input->{help_id} = $callIDsearch;
If some other part of your code modifies #callIDs, even after it's been assigned to $input->{help_id}, that could cause problems. Of course the fact that it's a lexical (my) variable means that any such changes to #callIDs are probably "nearby".
You could eliminate the named temporary array by doing the split like this:
$input->{help_id} = [ split(/,/,$callIDs) ];
I'm not sure I understand exactly why this is happening. It seems that your query builder needs an arrayref of strings. You can use map to do that
my $callIDs = '33450,31450';
my #callIDs = map {$_*1} split(/,/,$callIDs);
$input->{help_id} = \#callIDs;
This code should work
my $callIDs = '33450,31450';
$input->{help_id} = [split ",", $callIDs];
If your code somehow detect your data is number you can use
my $callIDs = '33450,31450';
$input->{help_id} = [map 0+$_, split ',', $callIDs];
If it somehow become number and you need string instead which should not in this case but advice for future work:
my $callIDs = '33450,31450';
$input->{help_id} = [map ''.$_, split ',', $callIDs];
I've been tasked with creating a new server modification for Crysis Wars. I have ran into a particular issue that it cannot read the old ban-file (this is required in order to keep the server consistent). The Lua code itself does not seem to have any errors, but it's just not getting any of the data.
Looking at the code I'm using for this below, can you find anything wrong with it?
This is the code I'm using for this:
function rX.CheckBanlist(player)
local Root = System.GetCVar("sys_root");
local File = ""..Root.."System/Bansystem/Raptor.xml";
local FileHnd = io.open(File, "r");
for line in FileHnd:lines() do
if (not string.find(line, "User:Read")) then
System.Log("[rX] File Read Error: System/Raptor/Banfile.xml, The contents are unexpected.");
return false;
end
local Msg, Date, Reason, Type, Domain = string.match(line, "User:Read( '(.*)', { Date='(.*)'; Reason='(.*)'; Typ='(.*)'; Info='(.*)'; } );");
local rldomain = g_gameRules.game:GetDomain(player.id);
if (Domain == rldomain) then
return true;
else
return false;
end
end
end
Also, the actual file reads as this, but I can't get the " to work in Lua properly. Could this be the issue?
User:Read( "Banned", { Date="31.03.2011"; Reason="WEBSTREAM"; Typ="Inetnum"; Info="COMPUTER.SED.gg"; } );
You may prefer using Lua's [[ for multiline string when you want to include quotes inside quotes etc.
Also, you'd have to escape the ( and ) while matching:
local Msg, Date, Reason, Type, Domain = line:match([[User:Read%( "(.-)", { Date="(.+)"; Reason="(.+)"; Typ="(.+)"; Info="(.+)"; } %);]])
And the results will be as expected: http://codepad.org/gN8kSL6H