I'm trying to fetch specific number of emails from Gmail using MailKit.net library.but there is an error while executing the search command:
The IMAP server replied to the 'SEARCH' command with a 'BAD' response
here is my code:
var startRange = (page - 1) * pageSize;
var endRage = page * pageSize;
var range = new UniqueIdRange(new UniqueId((uint)startRange),
new UniqueId((uint)endRage));
var uIds = Client.Inbox.Search(range, SearchQuery.All).Reverse();
and here is imap.log file content:
Connected to imaps://imap.gmail.com:993/
S: * OK Gimap ready for requests from 151.240.143.192 a1mb311709115lfh
C: A00000000 CAPABILITY
S: * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH
S: A00000000 OK Thats all she wrote! a1mb311709115lfh
C: A00000001 AUTHENTICATE PLAIN AHNhZS5oZW1tYXRpQGdtYWlsLmNvbSAAMDg2ODQxMTkxOTA4NjMx
S: * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- SPECIAL-USE APPENDLIMIT=35651584
S: A00000001 OK sae.hemmati#gmail.com authenticated (Success)
C: A00000002 NAMESPACE
S: * NAMESPACE (("" "/")) NIL NIL
S: A00000002 OK Success
C: A00000003 LIST "" "INBOX"
S: * LIST (\HasNoChildren) "/" "INBOX"
S: A00000003 OK Success
C: A00000004 LIST (SPECIAL-USE) "" "*"
S: * LIST (\All \HasNoChildren) "/" "[Gmail]/All Mail"
S: * LIST (\Drafts \HasNoChildren) "/" "[Gmail]/Drafts"
S: * LIST (\HasNoChildren \Sent) "/" "[Gmail]/Sent Mail"
S: * LIST (\HasNoChildren \Junk) "/" "[Gmail]/Spam"
S: * LIST (\Flagged \HasNoChildren) "/" "[Gmail]/Starred"
S: * LIST (\HasNoChildren \Trash) "/" "[Gmail]/Trash"
S: A00000004 OK Success
C: A00000005 LIST "" "[Gmail]"
S: * LIST (\HasChildren \Noselect) "/" "[Gmail]"
S: A00000005 OK Success
C: A00000006 EXAMINE INBOX (CONDSTORE)
S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing)
S: * OK [PERMANENTFLAGS ()] Flags permitted.
S: * OK [UIDVALIDITY 611076938] UIDs valid.
S: * 16612 EXISTS
S: * 0 RECENT
S: * OK [UIDNEXT 16834] Predicted next UID.
S: * OK [HIGHESTMODSEQ 1442114]
S: A00000006 OK [READ-ONLY] INBOX selected. (Success)
C: A00000007 UID SEARCH RETURN () UID 0:10
S: A00000007 BAD Could not parse command
Any clues?
thanks in advance!
Related
I am getting this IMAP response. Notice the folders INBOX.INBOX.ooo and INBOX.INBOX.dfgdfg. INBOX.INBOX folder doesn't exists and it is just a placeholder (NonExistent) folder.
C: A00000096 STATUS INBOX (UIDVALIDITY HIGHESTMODSEQ)
S: * STATUS INBOX (UIDVALIDITY 1491227400 HIGHESTMODSEQ 17436)
S: A00000096 OK Status completed (0.001 + 0.000 secs).
C: A00000097 LIST "" "INBOX.*" RETURN (SUBSCRIBED CHILDREN STATUS (UIDVALIDITY))
S: * LIST (\Subscribed \HasNoChildren \UnMarked) "." INBOX.INBOX.ooo
S: * STATUS INBOX.INBOX.ooo (UIDVALIDITY 1491227902)
S: * LIST (\HasNoChildren \UnMarked) "." INBOX.INBOX.dfgdfg
S: * STATUS INBOX.INBOX.dfgdfg (UIDVALIDITY 1491227900)
S: A00000097 OK List completed (0.001 + 0.000 secs).
However I can select this folder
A00000092 SELECT INBOX.INBOX (CONDSTORE)
S: * OK [CLOSED] Previous mailbox closed.
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted.
S: * 554 EXISTS
S: * 0 RECENT
S: * OK [UIDVALIDITY 1491227400] UIDs valid
S: * OK [UIDNEXT 18263] Predicted next UID
S: * OK [HIGHESTMODSEQ 17436] Highest
S: A00000092 OK [READ-WRITE] Select completed (0.001 + 0.000 secs).
So it appears that INBOX.INBOX is actually INBOX folder because UIDVALIDITY match and I can see the emails there. This is very confusing and it is messing my internal cache. Can someone explain what is going on?
UPDATE:
This might give some clues to someone
C: A00000001 NAMESPACE
S: * NAMESPACE (("INBOX." ".")) NIL NIL
S: A00000001 OK Namespace completed (0.001 + 0.000 secs).
C: A00000002 LIST "" "INBOX"
S: * LIST (\HasChildren) "." INBOX
S: A00000002 OK List completed (0.002 + 0.000 + 0.001 secs).
I have a Rails 4.2.6 app (also running Devise) in production with the Exception Notification gem installed and working. I get waves in hundreds of ActionController::InvalidAuthenticityToken errors (sample below), usually 2-3 per minute for hours at a time. I am not too clued up on the security side of Rails but I guess this is a robot attempting a CSRF attack of some form.
It always comes from the same IP address (107.15.69.216) which looks like one from Raleigh, North Carolina, USA.
Is it a robot?
And, Is there something I need to do about this or is the error simply proving that Devise's CSRF attack protection is working as it should?
An ActionController::InvalidAuthenticityToken occurred in registrations#create:
ActionController::InvalidAuthenticityToken
-------------------------------
Request:
-------------------------------
* URL : https://xxx.xxx.xxx.xxx/
* HTTP Method: POST
* IP address : 107.15.69.216
* Parameters : {"Q/Zcl9vJY8K1NPSRoHXnCQrZaPF8pu/uXVPyCfW8RnAQclIPvjOvpXqFLY TPUg9uBDmGWG5lMd8vzgSuGw79LAE d03xLFVtA/JUrX7cKmb3u Wrd7xS2LsMlSj2zAvtxmSPkGpoKR8e1p/XAQ exuiMte/fyXnLSrVjMfmzpNNxr7MSamyRHFVQan3LaxMJUq 02h4D1L4psFwbwl9k27W45G8FT9LaS2HG7g7y/rsxAon8ovLUgQNY2HcRMf7XlZxmxK20kDWfcLLn8DrpwY/bSW6mGsxAgD0CkapGj5LU7Smg5FvtR5qFn7q Ey9F0YdlMpE5/MqYWQNINgpzIxokxY1JyEdg5WphcGExuXjPDN3ChYUrkZG4h PAe7LuaGSQjyTOY/K4/O/iLODlBcM EqxCVZY8J04"=>nil, "controller"=>"registrations", "action"=>"create"}
* Timestamp : 2017-01-12 14:00:54 UTC
* Server : sgp1-iml-01
* Rails root : /home/app-name-deploy/apps/app-name/releases/20161212034105
* Process: 11031
-------------------------------
Session:
-------------------------------
* session id: [FILTERED]
* data: {}
-------------------------------
Environment:
-------------------------------
* CONTENT_LENGTH : 420
* CONTENT_TYPE : application/x-www-form-urlencoded
* GATEWAY_INTERFACE : CGI/1.2
* HTTP_CACHE_CONTROL : no-cache
* HTTP_CONNECTION : close
* HTTP_HOST : xxx.xxx.xxx.xxx
* HTTP_USER_AGENT : Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
* HTTP_VERSION : HTTP/1.0
* HTTP_X_FORWARDED_FOR : 107.15.69.216
* HTTP_X_FORWARDED_PROTO : https
* ORIGINAL_FULLPATH : /
* ORIGINAL_SCRIPT_NAME :
* PATH_INFO : /
* QUERY_STRING :
* REMOTE_ADDR : 127.0.0.1
* REQUEST_METHOD : POST
* REQUEST_PATH : /
* REQUEST_URI : /
* ROUTES_42047240_SCRIPT_NAME :
* SCRIPT_NAME :
* SERVER_NAME : xxx.xxx.xxx.xxx
* SERVER_PORT : 443
* SERVER_PROTOCOL : HTTP/1.1
* SERVER_SOFTWARE : puma 3.6.0 Sleepy Sunday Serenity
* action_controller.instance : #<RegistrationsController:0x00000006f6a0d0>
* action_dispatch.backtrace_cleaner : #<Rails::BacktraceCleaner:0x00000005458648>
* action_dispatch.cookies : #<ActionDispatch::Cookies::CookieJar:0x00000006f537b8>
* action_dispatch.cookies_digest :
* action_dispatch.cookies_serializer : json
* action_dispatch.encrypted_cookie_salt : encrypted cookie
* action_dispatch.encrypted_signed_cookie_salt : signed encrypted cookie
* action_dispatch.http_auth_salt : http authentication
* action_dispatch.key_generator : #<ActiveSupport::CachingKeyGenerator:0x00000006945560>
* action_dispatch.logger : #<ActiveSupport::Logger:0x00000006d22570>
* action_dispatch.parameter_filter : [:password]
* action_dispatch.redirect_filter : []
* action_dispatch.remote_ip : 107.15.69.216
* action_dispatch.request.content_type : application/x-www-form-urlencoded
* action_dispatch.request.formats : [#<Mime::Type:0x000000053404e0 #synonyms=["application/xhtml+xml"], #symbol=:html, #string="text/html", #hash=672552242721212245>]
* action_dispatch.request.parameters : {"Q/Zcl9vJY8K1NPSRoHXnCQrZaPF8pu/uXVPyCfW8RnAQclIPvjOvpXqFLY TPUg9uBDmGWG5lMd8vzgSuGw79LAE d03xLFVtA/JUrX7cKmb3u Wrd7xS2LsMlSj2zAvtxmSPkGpoKR8e1p/XAQ exuiMte/fyXnLSrVjMfmzpNNxr7MSamyRHFVQan3LaxMJUq 02h4D1L4psFwbwl9k27W45G8FT9LaS2HG7g7y/rsxAon8ovLUgQNY2HcRMf7XlZxmxK20kDWfcLLn8DrpwY/bSW6mGsxAgD0CkapGj5LU7Smg5FvtR5qFn7q Ey9F0YdlMpE5/MqYWQNINgpzIxokxY1JyEdg5WphcGExuXjPDN3ChYUrkZG4h PAe7LuaGSQjyTOY/K4/O/iLODlBcM EqxCVZY8J04"=>nil, "controller"=>"registrations", "action"=>"create"}
* action_dispatch.request.path_parameters : {:controller=>"registrations", :action=>"create"}
* action_dispatch.request.query_parameters : {}
* action_dispatch.request.request_parameters : {"Q/Zcl9vJY8K1NPSRoHXnCQrZaPF8pu/uXVPyCfW8RnAQclIPvjOvpXqFLY TPUg9uBDmGWG5lMd8vzgSuGw79LAE d03xLFVtA/JUrX7cKmb3u Wrd7xS2LsMlSj2zAvtxmSPkGpoKR8e1p/XAQ exuiMte/fyXnLSrVjMfmzpNNxr7MSamyRHFVQan3LaxMJUq 02h4D1L4psFwbwl9k27W45G8FT9LaS2HG7g7y/rsxAon8ovLUgQNY2HcRMf7XlZxmxK20kDWfcLLn8DrpwY/bSW6mGsxAgD0CkapGj5LU7Smg5FvtR5qFn7q Ey9F0YdlMpE5/MqYWQNINgpzIxokxY1JyEdg5WphcGExuXjPDN3ChYUrkZG4h PAe7LuaGSQjyTOY/K4/O/iLODlBcM EqxCVZY8J04"=>nil}
* action_dispatch.request.unsigned_session_cookie: {}
* action_dispatch.request_id : b8c1d2ef-0272-4e58-928d-8d02e8c5ad28
* action_dispatch.routes : #<ActionDispatch::Routing::RouteSet:0x00000005032e10>
* action_dispatch.secret_key_base : 72399ae7d71631b9bf5c19fe5e63e6e6c7163f37cdf8d1bb853cb77b53b6de0d20ce168a0e4a6fc87fadeb09b122a30d09ff9103f2f05a6bd5660c4c00f57392
* action_dispatch.secret_token :
* action_dispatch.show_detailed_exceptions : false
* action_dispatch.show_exceptions : true
* action_dispatch.signed_cookie_salt : signed cookie
* devise.mapping : #<Devise::Mapping:0x00000006939c60>
* puma.config : #<Puma::Configuration:0x00000002f1e940>
* puma.socket : #<UNIXSocket:0x00000006f768a8>
* rack.after_reply : []
* rack.errors : #<File:0x0000000230dac0>
* rack.hijack : #<Puma::Client:0x00000006f76880>
* rack.hijack? : true
* rack.input : #<StringIO:0x00000006f762b8>
* rack.multiprocess : false
* rack.multithread : true
* rack.request.cookie_hash : {}
* rack.request.form_hash : {"Q/Zcl9vJY8K1NPSRoHXnCQrZaPF8pu/uXVPyCfW8RnAQclIPvjOvpXqFLY TPUg9uBDmGWG5lMd8vzgSuGw79LAE d03xLFVtA/JUrX7cKmb3u Wrd7xS2LsMlSj2zAvtxmSPkGpoKR8e1p/XAQ exuiMte/fyXnLSrVjMfmzpNNxr7MSamyRHFVQan3LaxMJUq 02h4D1L4psFwbwl9k27W45G8FT9LaS2HG7g7y/rsxAon8ovLUgQNY2HcRMf7XlZxmxK20kDWfcLLn8DrpwY/bSW6mGsxAgD0CkapGj5LU7Smg5FvtR5qFn7q Ey9F0YdlMpE5/MqYWQNINgpzIxokxY1JyEdg5WphcGExuXjPDN3ChYUrkZG4h PAe7LuaGSQjyTOY/K4/O/iLODlBcM EqxCVZY8J04"=>nil}
* rack.request.form_input : #<StringIO:0x00000006f762b8>
* rack.request.form_vars : [FILTERED]
* rack.request.query_hash : {}
* rack.request.query_string :
* rack.run_once : false
* rack.session : #<ActionDispatch::Request::Session:0x00000006f6bea8>
* rack.session.options : #<ActionDispatch::Request::Session::Options:0x00000006f6be08>
* rack.url_scheme : http
* rack.version : [1, 3]
* warden : Warden::Proxy:58416640 #config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:rememberable, :database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x00000007b40dc8>}
Thanks
Yes. It is a bot. It is trying to go through your devise's registration form. Just in case check if you have this code in your main layout: <%= csrf_meta_tags %>. It can be accidently deleted after rewriting your layout.
This is the info about IP address from which you were under attack: http://pastebin.com/c1Zb5tcP
You can try to cut spammer using your resources with rack-attack gem
There is a simple configuration to start with it, after installation.
There is also another solution, to create a rule in the INPUT chain in your IPtables, and block traffic from the IP address you provided, in case that you have access to your server:
iptables -I INPUT -s 107.15.69.216 -j DROP
I am using powershell to perform a tracert command and putting the result into a variable.
$TraceResult = tracert $server
When using write-host the output looks fine on screen, which each hop on a new line.
Tracing route to fhotmail.com [65.55.39.10]
over a maximum of 30 hops:
1 <1 ms <1 ms <1 ms BTHomeHub.home [192.168.50.1]
2 * * * Request timed out.
3 * * * Request timed out.
4 * * * Request timed out.
5 * * * Request timed out.
When I output the variable to a file using add-content the return characters are lost and the formatting looks terrible as it's on one line:
17/06/2014 14:48:26 Tracing route to fhotmail.com [64.4.6.100] over a maximum of 30 hops: 1 <1 ms <1 ms <1 ms BTHomeHub.home [192.168.50.1] 2 * * * Request timed out. 3 * * * Request timed out. 4 * * * Request timed out. 5 * * * Request timed out. 6 * * * Request timed out. 7 * * * Request timed out. 8 * * * Request timed out. 9 * * * Request timed out. 10 * * * Request timed out. 11 * * * Request timed out. 12 * * * Request timed out. 13 * * * Request timed out. 14 * * * Request timed out. 15 * * * Request timed out. 16 * * * Request timed out. 17 * * * Request timed out. 18 * * * Request timed out. 19 * * * Request timed out. 20 * * * Request timed out. 21 * * * Request timed out. 22 * * * Request timed out. 23 * * * Request timed out. 24 * * * Request timed out. 25 * * * Request timed out. 26 * * * Request timed out. 27 * * * Request timed out. 28 * * * Request timed out. 29 * * * Request timed out. 30 * * * Request timed out. Trace complete.
Any idea on where I'm going wrong?
$servers = "localhost","google.com","fhotmail.com"
$Logfile = "c:\temp\$(Get-Content env:computername).log" # Sets the logfile as c:\temp\[COMPUTERNAME].log
# Countdown function with progress bar
Function Start-Countdown
{
Param(
[Int32]$Seconds = 10,
[string]$Message = "Pausing for 10 seconds..."
)
ForEach ($Count in (1..$Seconds))
{ Write-Progress -Id 1 -Activity $Message -Status "Waiting for $Seconds seconds, $($Seconds - $Count) left" -PercentComplete (($Count / $Seconds) * 100)
Start-Sleep -Seconds 1
}
Write-Progress -Id 1 -Activity $Message -Status "Completed" -PercentComplete 100 -Completed
}
# Log Write Function to log a message with date and time (tab delimited)
Function LogWrite
{
Param ([string]$logstring)
Add-content $Logfile -value "$(get-date -UFormat '%d/%m/%Y') `t$(get-date -UFormat '%T') `t$logstring"
}
# Looping script to run ping tests, then countdown for a period, before repeating
while ($true) {
# Ping servers and perform tracert if not responding to ping
foreach ( $server in $servers ) {
write-Host "Pinging: $server" -ForegroundColor Green
if ((test-Connection -ComputerName $server -Count 2 -Quiet) -eq $true ) {
# Ping response received.
write-Host "Response Received Sucessfully [$server].`n" -ForegroundColor Green
}
else {
# Ping response failed, next perform trace route.
write-Host "Response FAILED [$server]." -ForegroundColor RED
LogWrite "Ping Response FAILED [$server]."
Write-Host "Traceroute: $server - $(get-date -UFormat '%d/%m/%Y - %T')" -ForegroundColor Yellow
$TraceResult = tracert $server
LogWrite $TraceResult
Write-Host "Traceroute Completed [$server]`n" -ForegroundColor Yellow
}
}
# Pause before repeating
Start-Countdown -Seconds 60 -Message "Pausing script before restarting tests. Use CTRL-C to Terminate."
}
The output of tracert isn't being handled by PowerShell as a single string but rather an array of strings (one per line) and it's trying to force them all into a single string (concatenating them, basically).
Assuming you're OK with output like this:
17/06/2014 16:54:07
Tracing route to SERVERNAME [IP]
over a maximum of 30 hops:
1 1 ms <1 ms <1 ms HOP1
2 1 ms <1 ms <1 ms IP
Trace complete.
You'll need to do this:
$TraceResult = tracert $server
LogWrite ($TraceResult -join "`r`n")
This will concatenate all the elements of the $TraceResult array into one string, with CRLF as the EOL marker.
I am trying to split a string using an integer array as mask.
The task is simple but I am not accustomed to ADA (which is a constraint).
Here is my code. It works exept that I have an one character offset when testing against a file. Can someone help me remove this offset. it is drinving me nuts.
generic_functions.adb :
package body Generic_Functions is
-- | Sums up the elements of an array of Integers
function Sum_Arr_Int(Arr_To_Sum: Int_Array) return Integer is
Sum: Integer;
begin
Sum := 0;
for I in Arr_To_Sum'Range loop
Sum := Sum + Arr_To_Sum(I);
end loop;
return Sum;
end Sum_Arr_Int;
-- | Split up a String into a array of Unbounded_String following pattern from an Int_Array
function Take_Enregistrements(Decoup_Tab: Int_Array; Str_To_Read: String) return Str_Array is
Previous, Next : Integer;
Arr_To_Return : Str_Array(Decoup_Tab'Range);
begin
if Sum_Arr_Int(Decoup_Tab) > Str_To_Read'Length then
raise Constraint_Error;
else
Previous := Decoup_Tab'First;
Next := Decoup_Tab(Decoup_Tab'First);
for I in Decoup_Tab'Range loop
if I /= Decoup_Tab'First then
Previous := Next + 1;
Next := (Previous - 1) + Decoup_Tab(I);
end if;
Arr_To_Return(I) := To_Unbounded_String(Str_To_Read(Previous..Next));
end loop;
return Arr_To_Return;
end if;
end Take_Enregistrements;
end Generic_Functions;
generic_functions.ads :
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Generic_Functions is
-- | Types
type Int_Array is array(Positive range <>) of Integer;
type Str_Array is array(Positive range <>) of Unbounded_String;
-- | end of Types
-- | Functions
function Sum_Arr_Int(Arr_To_Sum: Int_Array) return Integer;
function Take_Enregistrements(Decoup_Tab: Int_Array; Str_To_Read: String) return Str_Array;
-- | end of Functions
end Generic_Functions;
generic_functions_tests.adb :
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Generic_Functions; use Generic_Functions;
procedure Generic_Functions_Tests is
-- | Variables
Decoup_Test : constant Int_Array(1..8) := (11, 19, 60, 24, 255, 10, 50, 255);
Test_Str_Arr : Str_Array(Decoup_Test'Range);
Test_Str_Arr2 : Str_Array(Decoup_Test'Range);
Test_Str_Arr3 : Str_Array(Decoup_Test'Range);
--Test_Int : Integer;
Test_Handle : File_Type;
-- | end of Variables
begin
Open(Test_Handle, In_File, "EXPORTFINAL.DAT");
Test_Str_Arr := Take_Enregistrements(Decoup_Test, Get_Line(Test_Handle));
Test_Str_Arr2 := Take_Enregistrements(Decoup_Test, Get_Line(Test_Handle));
Test_Str_Arr3 := Take_Enregistrements(Decoup_Test, Get_Line(Test_Handle));
for I in Test_Str_Arr'Range loop
Put_Line(To_String(Test_Str_Arr(I)));
end loop;
for I in Test_Str_Arr2'Range loop
Put_Line(To_String(Test_Str_Arr2(I)));
end loop;
for I in Test_Str_Arr3'Range loop
Put_Line(To_String(Test_Str_Arr3(I)));
end loop;
-- for I in Test_Str_Arr'Range loop
-- Test_Int := To_String(Test_Str_Arr(I))'Length;
-- Put_Line(Integer'Image(Test_Int));
-- end loop;
-- for I in Test_Str_Arr2'Range loop
-- Test_Int := To_String(Test_Str_Arr2(I))'Length;
-- Put_Line(Integer'Image(Test_Int));
-- end loop;
-- for I in Test_Str_Arr3'Range loop
-- Test_Int := To_String(Test_Str_Arr3(I))'Length;
-- Put_Line(Integer'Image(Test_Int));
-- end loop;
Close(Test_Handle);
end Generic_Functions_Tests;
and finaly the file:
000000000012012-01-01 10:00:00 IBM IBM COMPAGNIE IBM FRANCE 17 AVENUE DE l'EUROPE 92275 BOIS-COLOMBES CEDEX CONFIGURATION COMPLETE SERVEUR000000000000000000000019 .6000000000001000000000000000000001000.00000000000000000000000000000196.00000000000000000000000000001196.00000000
000000000022012-01-01 11:00:00 MICROSOFT MSC 39 QUAI DU PRESIDENT ROOSEVELT 92130 ISSY-LES-MOULINEAUX AMENAGEMENT SALLE INFORMATIQUE000000000000000000000019.6000000000001000000000000000000001000.00000000000000000000000000000196.00000000000000000000000000001196.00000000
000000000032012-01-01 12:00:00 MICROSOFT MSC 39 QUAI DU PRESIDENT ROOSEVELT 92130 ISSY-LES-MOULINEAUX TESTS SUR SITE000000000000000000000019.6000000000001000000000000000000003226.52000000000000000000000000000632.39792000000000000000000000003858.91792000 DELEGATION TECHNICIEN HARD000000000000000000000019.60000000000000000000000000000001.00000000000000000000000000001000.00000000000000000000000000000196.00000000000000000000000000001196.00000000
These lines:
if I = Decoup_Tab'Last then
Arr_To_Return(I) := To_Unbounded_String(Str_To_Read(Previous..Next));
end if;
will overwrite the last element in your array.
Also, are you sure that the line number (00000000001, 00000000002, etc) is one of the strings you want to split based on the integer mask? As your code is right now, you use '11' twice, once for the line number and once for the date-field. If you skip the line number, the other numbers seem to make more sense.
I now currently try to read .wav file using delphi here is my code :
type
TWaveHeader = packed record
Marker_RIFF: array [0..3] of char;
ChunkSize: cardinal;
Marker_WAVE: array [0..3] of char;
Marker_fmt: array [0..3] of char;
SubChunkSize: cardinal;
FormatTag: word;
NumChannels: word;
SampleRate: longint;
BytesPerSecond: longint;
BytesPerSample: word;
BitsPerSample: word;
Marker_data: array [0..3] of char;
DataBytes: longint;
end;
TChannel = record
Data : array of double;
end;
some private delcaration
private
wavehdr:TWaveHeader;
wavedata:array[0..3]of TChannel;
numsamples:integer;
the function
FillChar(wavehdr, sizeof(wavehdr), 0);
Stream.Read(wavehdr, sizeof(wavehdr));
{ Log Header data }
with memo1.Lines do begin
Add('Filename : '+od.FileName);
Add('Header size : '+inttostr(sizeof(wavehdr)));
tmpstr := wavehdr.Marker_RIFF;
Add('RIFF ID : '+tmpstr+'');
Add('Chunk size : '+inttostr(wavehdr.ChunkSize));
tmpstr := wavehdr.Marker_WAVE;
Add('WAVE ID : '+tmpstr+'');
tmpstr := wavehdr.Marker_fmt;
Add('''fmt '' ID : '+tmpstr+''' ');
Add('SubChunk size : '+inttostr(wavehdr.SubChunkSize));
Add('Format : '+inttostr(wavehdr.FormatTag));
Add('Num Channels : '+inttostr(wavehdr.NumChannels));
Add('Sample rate : '+inttostr(wavehdr.SampleRate));
Add('Bytes per second : '+inttostr(wavehdr.BytesPerSecond));
Add('Bits per sample : '+inttostr(wavehdr.BitsPerSample));
Add('Block Align : '+inttostr((wavehdr.NumChannels*wavehdr.BitsPerSample)div 8));
end;
numsamples := (file.size div (wavehdr.NumChannels*wavehdr.BitsPerSample)div 8) div wavehdr.BytesPerSample;
case wavehdr.NumChannels of
1:begin
SetLength(wavedata[0].Data, numsamples);
Stream.Read(wavedata[0].Data[0], numsamples);
end;
2:begin
SetLength(wavedata[0].Data, numsamples);
SetLength(wavedata[1].Data, numsamples);
for i := 0 to high(wavedata[0].Data) do begin
Stream.Read(wavedata[0].Data[i], 2);
Stream.Read(wavedata[1].Data[i], 2);
end;
end;
end;
Above code give me the exact same information and detail about the .wav header (same as MATLAB DOES) which is :
Filename : E:\dephi\classic3.wav
RIFF ID : RIFF
Chunk size : 18312354
WAVE ID : WAVE
'fmt ' ID : fmt '
SubChunk size : 16
Format : 1 (PCM)
Num Channels : 2 (Stereo)
Sample rate : 44100
Bytes per second : 176400
Bits per sample : 16
Block Align : 4
Except the Total Sample Data Which i calculated by (size of wavedata/ blockalign of wavedata)-44, 44 is header of wav. It's not accurate, sometimes is miss by 5,1,10 . I have only tested using 5 sample.And here an example :
classic1.wav matlab:3420288, delphi(my calculation):(13681352/4)-44= 3420294
classic2.wav matlab:2912256, delphi(my calculation):(11649204/4)-44= 2912257
And also the sample data value from matlab and delphi is different like
classic1.wav
MATLAB:(first 10 value leftchannel and rightchannel)
-3.05175781250000e-05 [] 6.10351562500000e-05
-6.10351562500000e-05 [] 6.10351562500000e-05
-6.10351562500000e-05 [] 3.05175781250000e-05
0 [] -3.05175781250000e-05
6.10351562500000e-05 [] -6.10351562500000e-05
6.10351562500000e-05 [] -6.10351562500000e-05
3.05175781250000e-05 [] -3.05175781250000e-05
6.10351562500000e-05 [] -6.10351562500000e-05
3.05175781250000e-05 [] 0
-3.05175781250000e-05 [] 6.10351562500000e-05
DELPHI:(first 10 value leftchannel and rightchannel)
9.90156960830442E-320 [] 1.00265682167023E-319
9.90156960830442E-320 [] 9.77113627780233E-320
3.26083326255223E-322 [] 0
1.39677298735779E-319 [] 1.37088394751571E-319
1.45932169812129E-319 [] 1.33373021094845E-319
1.23175506164681E-319 [] 1.206903559661E-319
1.28239679034554E-319 [] 1.40932225476216E-319
1.37068632125737E-319 [] 1.33382902407761E-319
1.33373021094845E-319 [] 1.25685359645555E-319
1.40907522193924E-319 [] 1.33358199125469E-319
My question are :
When Finding the total sample of the wav file, how to do it correctly?
Are the way matlab and delphi reading wav file (data chunk) in a
different way? or maybe my code was the one here is wrong?
Is there a way to get the same value like MATLAB does?
EDIT : i followed mBo advise and changed it into mbo advise
Data : array of SmallInt;
numsamples := wavehdr.DataBytes div (wavehdr.NumChannels * wavehdr.BitsPerSample div 8);
Stream.Read(wavedata[0].Data[i], SizeOf(SmallInt));
the interpreting part i'm not sure but i changed it into
floattostr(wavedata[0].Data[i]/32768.0)
floattostr(wavedata[1].Data[i]/32768.0)
the result i get :
0.611602783203125 [] 0.61932373046875
0.611602783203125 [] 0.603546142578125
0.0023193359375 [] 0
0.862762451171875 [] 0.846771240234375
0.901397705078125 [] 0.823822021484375
0.760833740234375 [] 0.7454833984375
0.7921142578125 [] 0.870513916015625
0.799774169921875 [] 0.761016845703125
0.8238525390625 [] 0.782623291015625
0.354766845703125 [] 0.76123046875
Wav-file (Bits per sample : 16) contains signed 16 bit integer data (SmallInt type), but you read data in float 8-byte type Double array.
You can declare
Data : array of SmallInt;
calculate
numsamples := wavehdr.DataBytes div (wavehdr.NumChannels * wavehdr.BitsPerSample div 8);
read them as
Stream.Read(wavedata[0].Data[0], numsamples * SizeOf(SmallInt))
or multichannel case:
Stream.Read(wavedata[0].Data[i], SizeOf(SmallInt));
and then interpret data values as floats Data[i] / 32768.0
note that matlab value 3.05175781250000e-05 = 1/32768.0 is minimal quantum of 16-bit signal