tag:blogger.com,1999:blog-58830119347201634422024-02-20T09:24:07.358+01:00mindc.netnothing can prepare you...Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.comBlogger32125tag:blogger.com,1999:blog-5883011934720163442.post-83340187293257109002015-06-03T10:36:00.001+02:002017-08-21T09:31:29.975+02:00Aplikacja LINE, protokół Thrift i PerlWszystkie skrypty jakie znalazłem w sieci, które logowały się do LINE, były napisane głównie w języku Python, a ja niestety programuję w Perl. Więc po dwóch dniach walk, na podstawie znalezionego kodu w sieci, stworzyłem skrypt który loguje się do LINE i pobiera dane użytkownika. Inne funkcje można podejrzeć w pliku <code>TalkService.pm</code>
<pre>
#!/usr/bin/perl
package customHttpClient;
use base qw(Thrift::HttpClient);
sub setCustomHeader {
my $self = shift;
push @{$self->{'customHeaders'}},[@_];
}
sub flush
{
my $self = shift;
my $ua = LWP::UserAgent->new('timeout' => 1);
$ua->default_header('Accept' => 'application/x-thrift');
$ua->default_header('Content-Type' => 'application/x-thrift');
$ua->cookie_jar({}); # hash to remember cookies between redirects
my $out = $self->{out};
$out->setpos(0); # rewind
my $buf = join('', <$out>);
my $request = new HTTP::Request(POST => $self->{url}, undef, $buf);
foreach ( @{$self->{'customHeaders'}} ) {
$request->header(@$_);
}
my $response = $ua->request($request);
my $content_ref = $response->content_ref;
my $in = IO::String->new($content_ref);
binmode($in);
$self->{in} = $in;
$in->setpos(0); # rewind
# reset write buffer
$out = IO::String->new;
binmode($out);
$self->{out} = $out;
}
package main;
use strict;
use warnings;
use Data::Dumper;
use Thrift::XS;
use TalkService;
use Try::Tiny;
use constant LINE_DOMAIN => "http://125.209.252.15";
use constant LINE_HTTP_URL => LINE_DOMAIN . "/api/v4/TalkService.do";
my $ip = "127.0.0.1";
my $version = "4.0.2.366";
my $com_name = "LineJ";
my $id = '<email>';
my $password = '<password>';
my $os_version = "6.2.9200-8-x64";
my $user_agent = sprintf("DESKTOP:WINDOWS:%s(%s)",$os_version,$version);
my $app = sprintf("DESKTOPWIN\t%s\tWINDOWS\t%s",$version, $os_version);
my $transport = new customHttpClient(LINE_HTTP_URL);
$transport->setCustomHeader('User-Agent' => $user_agent);
$transport->setCustomHeader('X-Line-Application' => $app);
my $protocol = new Thrift::XS::CompactProtocol($transport);
my $client = new TalkServiceClient($protocol);
try {
my $msg = $client->loginWithIdentityCredentialForCertificate(
IdentityProvider::LINE, $id, $password, 0, $ip, $com_name, ""
);
$transport->setCustomHeader('X-Line-Access' => $msg->{authToken});
print Dumper $client->getProfile();
} catch {
print STDERR Dumper $_;
};
exit;
</pre>
Moduł <code>TalkService</code> wygenerowałem na podstawie pliku <a href="https://github.com/cslinmiso/LINE-instant-messenger-protocol/blob/master/line.thrift">line.thrift</a>. Informacje jak wygenerować kod w Perlu (i nie tylko) znajdują się pod adresem <a href="https://thrift.apache.org/tutorial/">https://thrift.apache.org/tutorial/</a>.
Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-1807823068970830722014-01-08T10:31:00.002+01:002014-01-08T10:41:41.190+01:00Ubiquiti TOUGHSwitch PoE PRO i stany liczników (ruch) dla każdego portu<p>Odczytanie zawartości <code>/proc/net/dev</code> nic nie mówi o ruchu na portach, jedynie na wewnętrznych interfejsach switch'a. Aby uzyskać stany liczników (ruch) dla każdego z portów osobno, wystarczy otworzyć plik <code>/var/tmp/status_json</code>.</p>
Przykładowa zawartość, format JSON:<pre>{
"stats":{
"1":{
"poe":"0",
"portSpeed":"100",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":117754941658,
"TxBroad":110690,
"TxUni":111089346,
"TxMulti":93541,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":27881914005,
"RxBroad":46508,
"RxUni":88242095,
"RxMulti":1395,
"RxFcsErr":1,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":40993599,
"TRx128Byte":25693523,
"TRx256Byte":3648856,
"TRx512Byte":1990133,
"TRx1024Byte":2362312,
"TRxMaxByte":13601576
}
},
"2":{
"poe":"0",
"portSpeed":"1000",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":163126309,
"TxBroad":1432704,
"TxUni":453,
"TxMulti":567588,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":3241577,
"RxBroad":0,
"RxUni":1,
"RxMulti":6191,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":34,
"TRx128Byte":0,
"TRx256Byte":0,
"TRx512Byte":2471,
"TRx1024Byte":3687,
"TRxMaxByte":0
}
},
"3":{
"poe":"0",
"portSpeed":"1000",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":163682077,
"TxBroad":1433291,
"TxUni":502,
"TxMulti":567350,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":2740019,
"RxBroad":0,
"RxUni":0,
"RxMulti":6511,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":6,
"TRx128Byte":0,
"TRx256Byte":0,
"TRx512Byte":6505,
"TRx1024Byte":0,
"TRxMaxByte":0
}
},
"4":{
"poe":"0",
"portSpeed":"1000",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":1393171085555,
"TxBroad":1431210,
"TxUni":1290915353,
"TxMulti":573720,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":156045432312,
"RxBroad":328,
"RxUni":958413239,
"RxMulti":4056,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":498122212,
"TRx128Byte":318655134,
"TRx256Byte":54161969,
"TRx512Byte":17977988,
"TRx1024Byte":23049878,
"TRxMaxByte":46450443
}
},
"5":{
"poe":"0",
"portSpeed":"1000",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":1336905838571,
"TxBroad":241505,
"TxUni":3710249743,
"TxMulti":496286,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":12183648616197,
"RxBroad":1178135,
"RxUni":2229543132,
"RxMulti":77472,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":657162412,
"TRx128Byte":1339531801,
"TRx256Byte":523701573,
"TRx512Byte":313405085,
"TRx1024Byte":246887664,
"TRxMaxByte":3445300570
}
},
"6":{
"poe":"0",
"portSpeed":"100",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":45602466100,
"TxBroad":151096,
"TxUni":42552269,
"TxMulti":92342,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":3575597265,
"RxBroad":26,
"RxUni":29139075,
"RxMulti":2768,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":17438436,
"TRx128Byte":8498808,
"TRx256Byte":1561161,
"TRx512Byte":406953,
"TRx1024Byte":563539,
"TRxMaxByte":672972
}
},
"7":{
"poe":"0",
"portSpeed":"1000",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":3208892838838,
"TxBroad":1256802,
"TxUni":2760667465,
"TxMulti":400569,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":293912171364,
"RxBroad":176646,
"RxUni":2009603876,
"RxMulti":173290,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":1068232579,
"TRx128Byte":683150554,
"TRx256Byte":96470449,
"TRx512Byte":39277959,
"TRx1024Byte":46666621,
"TRxMaxByte":76155650
}
},
"8":{
"poe":"0",
"portSpeed":"100",
"linkStatus":"1",
"duplex":"1",
"hasVlans":"0",
"maxFrameSize":"1518",
"alertEnabled":"0",
"stpState":"No spanning",
"stats":{
"TxByte":7436383703602,
"TxBroad":1352989,
"TxUni":2343144437,
"TxMulti":267006,
"TxExcCol":0,
"TxLateCol":0,
"RxGoodByte":873321777726,
"RxBroad":32306,
"RxUni":648949666,
"RxMulti":310287,
"RxFcsErr":0,
"RxAllignErr":0,
"RxJabber":0,
"RxFragment":0,
"RxOversize":0,
"TRx64Byte":2512756819,
"TRx128Byte":1695780622,
"TRx256Byte":226916928,
"TRx512Byte":98845703,
"TRx1024Byte":121118002,
"TRxMaxByte":289468496
}
}
},
"timestamp":1389173254.935458,
"now":"2014-01-08 10:27:34",
"uptime":"506585",
"management":{
"up":1,
"speed":100
}
}</pre>
Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-84353517996332164042012-10-25T12:23:00.001+02:002012-10-25T12:23:51.006+02:00'iptables' i szybkie usuwanie wszystkich reguł...<p>Poniżej szybkie usuwanie wszystkich reguł z <code>iptables</code>. Zarówno z wbudowanych łańcuchów jak i z łańcuchów użytkownika.</p>
<pre>#!/bin/bash
echo "*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
" | iptables-restore
</pre>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-66567241679205765362012-10-22T10:02:00.001+02:002012-10-22T10:41:09.084+02:00Ubiquiti, SSH i zmiana hasła<p>Zmianę hasła w Ubiquiti, można przeprowadzić w poniższych krokach:</p>
<ol>
<li><p>Najpierw znajdujemy zmieniane hasło dla danego użytkownika.</p><pre>
# konsola Ubiquiti
cat /tmp/system.cfg | grep users.1.password | cut -d= -f2
</pre></li>
<li><p>Teraz ze starego hasła odzyskujemy <em>salt</em>, czyli w Ubiquiti dwa pierwsze znaki hasła.</p><pre>
# Perl
my $salt;
($salt) = $old_password =~ m/^(..)/; </pre>
<pre># BASH
SALT=`echo ${OLD_PASSWORD} | cut -c1,2`</pre></p></li>
<li>Generujemy nowe hasło.<pre># Perl
my $new_password_crypted = crypt($new_password,$salt);</pre></li>
<li><p>Mając wszystkie potrzebne dane, podmieniamy hasło.</p><pre># konsola Ubiquiti
sed -e 's/$old_password/$new_password_crypted/' /tmp/system.cfg
# zapisujemy zmiany
cfgmtd -w
</pre></li>
<li>Gotowe</li>
</ol>
<p>Powyższa procedura działa, jak na razie, na wszystkich dostępnych mi urządzeniach Ubiquiti.</p>
<p>Gotowy skrypt w Perlu: <a href="http://zeus.mindc.net/files/chpasswd-ubiquiti.pl">chpasswd-ubiquiti.pl</a></p> Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com2tag:blogger.com,1999:blog-5883011934720163442.post-8153800819283382522012-10-18T15:55:00.000+02:002012-10-22T10:03:40.256+02:00Ubiquiti i zmiana MAC adresu<p>Aby zmienić adres MAC interfejsu radiowego w Ubiquiti, możemy go po prostu zmienić za pomocą polecenia <code>ifconfig</code>.</p>
<p>Jednak zmiany te, nie zachowują się po restarcie urządzenia. Należy więc zmieniać adres MAC po każdym starcie systemu, a prosty skrypt ustawiający nowy adres zapisać w pamięci nieulotnej.</p>
<p>Poniżej procedura zmiany adresu MAC:</p>
<ol>
<li>Edytujemy plik <em>/etc/persistent/rc.poststart</em>. Jeśli pliku brak, tworzymy go.</li>
<li>Edytujemy zawartość pliku tak, aby zawierał poniższy kod:<pre>ifconfig ath0 down
ifconfig ath0 hw ether <em>XX:XX:XX:XX:XX:XX</em>
ifconfig ath0 up</pre>
Wartość <em>XX:XX:XX:XX:XX:XX</em> należy zastąpić nowym adresem MAC
</li>
<li>Zapisujemy dane do pamięci nieulotnej, uwzględniając pliki w <code>/etc</code>, wykonując polecenie <code>cfgmtd -w -p /etc/</code></li>
<li>Gotowe</li>
</ol>
<p>Po zrestartowaniu urządzenia, adres MAC będzie ustawiany na nową wartość</p>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-976287902008556392012-10-18T15:41:00.001+02:002012-10-18T15:57:55.577+02:00Ubiquiti airFiber 24G i SSH<p>W airFiber dane od interfejsach (liczniki) uzyskiwane przy pomocy <code>ifconfig</code> albo <code>cat /proc/net/dev</code> nie są adekwatne do oczekiwanych wartości.<br/>Po krótkich poszukiwaniach okazało się, że wszystkie te dane można wyciągnąć przy pomocy komendy <code>af</code></p>
<p>Pobieranie informacji odbywa się za pomocą komendy <code>af get <em>parametr</em></code></p>
<p>Poniżej pełna lista parametrów, wynik wywołania <code>aflist</code>. Zwracam uwagę na pogrubione nazwy parametrów:</p>
<pre>-------------------
AirFiber State Dump
-------------------
<b>frequency</b>.................24.2GHz
choices {24.1GHz,24.2GHz}
<b>rxfrequency</b>...............24.1GHz
choices {24.1GHz,24.2GHz}
<b>txfrequency</b>...............24.2GHz
choices {24.1GHz,24.2GHz}
rxgain....................high
choices {low,high}
txmodrate.................6x
duplex....................full
choices {half,full}
dpstat....................1000Mbps-Full
dpcntl....................auto
choices {auto,10Mbps-Half,100Mbps-Half,10Mbps-Full,100Mbps-Full}
gpspulse..................detected
choices {none,detected}
gpsfix....................3D fix
gpslat....................5333.98849N
gpslong...................02100.71451E
gpsalt....................171.6
gpsviewcnt................10
gpsusedcnt................10
gpshdop...................1.00
<b>rssi</b>......................51
<b>rssi0</b>.....................51
<b>rssi1</b>.....................51
rxpower...................-57
rxpower0..................-57
rxpower1..................-57
led.......................power
choices {rssi,power}
temp0.....................34
temp1.....................34
getlist...................frequency,rxfrequency,txfrequency,rxgain,txmodrate,duplex,dpstat,dpcntl,gpspulse,gpsfix,gpslat,gpslong,gpsalt,gpsviewcnt,gpsusedcnt,gpshdop,rssi,rssi0,rssi1,rxpower,rxpower0,rxpower1,led,temp0,temp1,getlist,setlist,countrycode,countrydom,speed,modcontrol,gps,powerout,mode,state,status,mastertxstart,mastertxlength,masterrxstart,masterrxlength,slavetxstart,slavetxlength,slaverxstart,slaverxlength,tdelay,feet,miles,meters,kilometers,linkname,key,capacity,rxcapacity,txcapacity,rrxpower0,rrxpower1,rtxmodrate,rpowerout,linktest,caldcoff,caltcxo,caltxiq,calrxiq,caltxtc,calrxtc,caltxpower,calrxpower,calpodc,mac_0,mac_1,TxFramesOK,RxFramesOK,RxFrameCrcErr,RxAlignErr,TxOctetsOK,RxOctetsOK,TxPauseFrames,RxPauseFrames,RxErroredFrames,TxErroredFrames,RxValidUnicastFrames,RxValidMulticastFrames,RxValidBroadcastFrames,TxValidUnicastFrames,TxValidMulticastFrames,TxValidBroadcastFrames,RxDroppedMacErrFrames,RxTotalOctets,RxTotalFrames,RxLess64ByteFrames,RxOverLengthFrames,Rx64BytePackets,Rx65_127BytePackets,Rx128_255BytePackets,Rx256_511BytePackets,Rx512_1023BytePackets,Rx1024_1518BytesPackets,Rx1519PlusBytePackets,RxTooLongFrameCrcErr,RxTooShortFrameCrcErr,phy00,phy01,phy02,phy03,phy04,phy05,phy06,phy07,phy08,phy09,phy0a,phy0b,phy0c,phy0d,phy0e,phy0f,phy10,phy11,phy12,phy13,phy14,phy15,phy16,phy17,phy18,phy19,phy1a,phy1b,phy1c,phy1d,phy1e,phy1f,txqosoct0,txqosoct1,txqosoct2,txqosoct3,txqosoct4,txqosoct5,txqosoct6,txqosoct7,txqosoct8,txqosoct9,txqosocta,txqosoctb,txqosoctc,txqosoctd,txqosocte,txqosoctf,txqospkt0,txqospkt1,txqospkt2,txqospkt3,txqospkt4,txqospkt5,txqospkt6,txqospkt7,txqospkt8,txqospkt9,txqospkta,txqospktb,txqospktc,txqospktd,txqospkte,txqospktf,rxqosoct0,rxqosoct1,rxqosoct2,rxqosoct3,rxqosoct4,rxqosoct5,rxqosoct6,rxqosoct7,rxqosoct8,rxqosoct9,rxqosocta,rxqosoctb,rxqosoctc,rxqosoctd,rxqosocte,rxqosoctf,rxqospkt0,rxqospkt1,rxqospkt2,rxqospkt3,rxqospkt4,rxqospkt5,rxqospkt6,rxqospkt7,rxqospkt8,rxqospkt9,rxqospkta,rxqospktb,rxqospktc,rxqospktd,rxqospkte
setlist...................frequency,rxfrequency,txfrequency,rxgain,duplex,dpcntl,led,countrycode,countrydom,speed,modcontrol,gps,powerout,mode,linkname,key,linktest,caldcoff,caltcxo,caltxiq,calrxiq,caltxtc,calrxtc,caltxpower,calrxpower,calpodc,phy00,phy04,phy07,phy09,phy10,phy12,phy14,phy18,phy19,phy1d,phy1e
countrycode...............840
countrydom................fcc
choices {none,fcc,etsi}
speed.....................6x
choices {1x,2x,4x,6x,8x}
modcontrol................automatic
choices {manual,automatic}
gps.......................on
choices {off,on}
powerout..................20
range {0..33}
mode......................slave
choices {master,slave,reset}
state.....................operational
status....................slave-operational
mastertxstart.............0
mastertxlength............1895544
masterrxstart.............1907506
masterrxlength............1895544
slavetxstart..............1901794
slavetxlength.............1895544
slaverxstart..............0
slaverxlength.............1895544
tdelay....................2856
feet......................2809
miles.....................0.532
meters....................856
kilometers................0.856
<b>linkname</b>..................spy-nid.........................
key.......................0000:0000:0000:0000:0000:0000:0000:0000
range {0000:0000:0000:0000:0000:0000:0000:0000..ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff}
<b>capacity</b>..................743339520
<b>rxcapacity</b>................743339520
<b>txcapacity</b>................743626240
rrxpower0.................-59
rrxpower1.................-60
rtxmodrate................6x
rpowerout.................20
linktest..................rx,0,tx,0,No Data
range {1..60}
caldcoff..................TX0DCI=0x091F,TX0DCQ=0x0154,TX1DCI=0x0CD5,TX1DCQ=0xFDB0
caltcxo...................TCXOcount=124999994
caltxiq...................TX0AI=0x0F6F,TX0AQ=0x0409,TX1AI=0x0F67,TX1AQ=0x0403
calrxiq...................RX0AI=0x0FFD,RX0AQ=0x0403,RX1AI=0x0FFE,RX1AQ=0x0409
caltxtc...................TCTX0gm40=-2.12,TCTX0gm15=-1.76,TCTX0gp10=-0.98,TCTX0gp35=0.00,TCTX0gp60=1.64,TCTX0gp85=3.41,TCTX1gm40=-2.12,TCTX1gm15=-1.76,TCTX1gp10=-0.98,TCTX1gp35=0.00,TCTX1gp60=1.64,TCTX1gp85=3.41
calrxtc...................TCRX0gm40=-5.20,TCRX0gm15=-2.93,TCRX0gp10=-1.58,TCRX0gp35=0.00,TCRX0gp60=1.92,TCRX0gp85=3.91,TCRX1gm40=-5.20,TCRX1gm15=-2.93,TCRX1gp10=-1.58,TCRX1gp35=0.00,TCRX1gp60=1.92,TCRX1gp85=3.91
caltxpower................TX0P=0x1D,TX0PdBm=6.92,TX0PTEMP=48,TX1P=0x1D,TX1PdBm=7.41,TX1PTEMP=48
calrxpower................RX0P=0x39,RX0PdBm=-50.00,RX0PTEMP=47,RX1P=0x39,RX1PdBm=-50.00,RX1PTEMP=48
calpodc...................P0short=0.00,P0half=0.00,P0full=-2.00,P1short=0.00,P1half=0.00,P1full=-2.00
mac_0.....................0
mac_1.....................0
<b>TxFramesOK</b>................2713099372
<b>RxFramesOK</b>................1103621960
RxFrameCrcErr.............0
RxAlignErr................0
<b>TxOctetsOK</b>................3728254389
<b>RxOctetsOK</b>................1000856066
TxPauseFrames.............0
RxPauseFrames.............0
RxErroredFrames...........1
TxErroredFrames...........63692
RxValidUnicastFrames......1099572717
RxValidMulticastFrames....601489
RxValidBroadcastFrames....3451960
TxValidUnicastFrames......2691192694
TxValidMulticastFrames....1670070
TxValidBroadcastFrames....20308518
RxDroppedMacErrFrames.....0
<b>RxTotalOctets</b>.............3687124683
<b>RxTotalFrames</b>.............1103629815
RxLess64ByteFrames........0
RxOverLengthFrames........0
Rx64BytePackets...........2153589453
Rx65_127BytePackets.......2333775463
Rx128_255BytePackets......268202900
Rx256_511BytePackets......145549651
Rx512_1023BytePackets.....136029207
Rx1024_1518BytesPackets...361452237
Rx1519PlusBytePackets.....0
RxTooLongFrameCrcErr......0
RxTooShortFrameCrcErr.....0
phy00.....................0x1000
phy01.....................0x796d
phy02.....................0x004d
phy03.....................0xd072
phy04.....................0x1de1
phy05.....................0xc5e1
phy06.....................0x000f
phy07.....................0x2801
phy08.....................0x0000
phy09.....................0x0200
phy0a.....................0x3800
phy0b.....................0x0000
phy0c.....................0x0000
phy0d.....................0x0000
phy0e.....................0x0000
phy0f.....................0xa000
phy10.....................0x0862
phy11.....................0xbc5c
phy12.....................0x0000
phy13.....................0x7401
phy14.....................0x082c
phy15.....................0x0000
phy16.....................0x04e8
phy17.....................0x0000
phy18.....................0x3200
phy19.....................0x3000
phy1a.....................0x0000
phy1b.....................0x063e
phy1c.....................0x0000
phy1d.....................0x000b
phy1e.....................0x2c20
phy1f.....................0x8100
txqosoct0.................0x0000000000000000
txqosoct1.................0x0000000000000000
txqosoct2.................0x0000000000000000
txqosoct3.................0x000000ed33db2544
txqosoct4.................0x0000000000000000
txqosoct5.................0x0000000000000000
txqosoct6.................0x0000000000000000
txqosoct7.................0x0000000000000000
txqosoct8.................0x0000000000000000
txqosoct9.................0x0000000000000000
txqosocta.................0x0000000000000000
txqosoctb.................0x0000000000000000
txqosoctc.................0x0000000000000ea7
txqosoctd.................0x0000000000000000
txqosocte.................0x0000000000000000
txqosoctf.................0x0000000000000000
txqospkt0.................0x0000000000000000
txqospkt1.................0x0000000000000000
txqospkt2.................0x0000000000000000
txqospkt3.................0x0000000141c446c5
txqospkt4.................0x0000000000000000
txqospkt5.................0x0000000000000000
txqospkt6.................0x0000000000000000
txqospkt7.................0x0000000000000000
txqospkt8.................0x0000000000000000
txqospkt9.................0x0000000000000000
txqospkta.................0x0000000000000000
txqospktb.................0x0000000000000000
txqospktc.................0x0000000000000017
txqospktd.................0x0000000000000000
txqospkte.................0x0000000000000000
txqospktf.................0x0000000000000000
rxqosoct0.................0x0000000000000000
rxqosoct1.................0x0000000004a95cdf
rxqosoct2.................0x0000000000000000
rxqosoct3.................0x000006da147ca526
rxqosoct4.................0x0000000000000000
rxqosoct5.................0x0000000000000000
rxqosoct6.................0x0000000000000000
rxqosoct7.................0x0000000000000000
rxqosoct8.................0x0000000000000000
rxqosoct9.................0x0000000000000000
rxqosocta.................0x0000000012b24e9c
rxqosoctb.................0x0000000000000000
rxqosoctc.................0x000000001159c6c1
rxqosoctd.................0x0000000000000000
rxqosocte.................0x0000000000000000
rxqosoctf.................0x0000000000000000
rxqospkt0.................0x0000000000000000
rxqospkt1.................0x000000000003b870
rxqospkt2.................0x0000000000000000
rxqospkt3.................0x00000001a1741f99
rxqospkt4.................0x0000000000000000
rxqospkt5.................0x0000000000000000
rxqospkt6.................0x0000000000000000
rxqospkt7.................0x0000000000000000
rxqospkt8.................0x0000000000000000
rxqospkt9.................0x0000000000000000
rxqospkta.................0x00000000001f35e9
rxqospktb.................0x0000000000000000
rxqospktc.................0x0000000000209e5a
rxqospktd.................0x0000000000000000
rxqospkte.................0x0000000000000000
</pre>
<p>Więc aby wyciągnąć dane z liczników i wykorzystać je na przykład w <code>rrdtool</code>, wystarczy odczytać wyniki dwóch komend:<br>
<pre>af get TxOctetsOK
af get RxOctetsOK</pre>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-52822922015214641572012-10-05T14:51:00.000+02:002013-06-07T12:05:47.169+02:00Skaner Ubiquiti<p>Skaner do urządzeń Ubiquiti dla konsoli linuksowej, napisany w Perlu.</p>
<p>Historia zmian:
<ul>
<li>2013-06-07<br/>
dodano nowy kod hardware'u: 'WM5'<br/>
<li>2012-12-17<br/>
dodano nowy kod hardware'u: 'NB2'<br/>
<li>2012-10-05<br/>
dodano nowy kod hardware'u: 'AF24'<br/>
dodano możliwość wybrania interfejsu do skanowania, podawany jako parametr wywołania skryptu<br/>
</li>
<li>2012-08-24<br/>
dodano rozpoznawanie kodow hardware'u: 'NS3','B2N','BS2' <br/>
</li>
<li>2012-08-22<br/>
poprawiono parsowanie odbieranego pakietu <br/>
poprawiono parsowanie wersji software <br/>
</li>
<li>2011-06-11<br/>
przepisano engine na klasyczne sockety <br/>
</li>
<li>2011-03-20<br/>
pierwsza wersja<br/>
</li>
</ul>
</p>
<p>Najbardziej aktualna wersja skanera: <a href="http://zeus.mindc.net/files/scan-ubiquiti.pl">scan-ubiquiti.pl</a></p>
Opisy:
<ul><li><a href="http://blog.mindc.net/2011/03/ubiquiti.html">http://blog.mindc.net/2011/03/ubiquiti.html</a></li>
<li><a href="http://blog.mindc.net/2011/06/ubiquiti-cz2.html">http://blog.mindc.net/2011/06/ubiquiti-cz2.html</a></li>
<li><a href="http://blog.mindc.net/2012/08/ubiquiti-cz3.html">http://blog.mindc.net/2012/08/ubiquiti-cz3.html</a></li>
</ul>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-18637932695472350262012-08-22T19:36:00.000+02:002012-08-24T17:44:57.222+02:00Ubiquiti cz.3Dzisiaj coś mi nie pasowało w moim skanerze, okazało się że za bardzo zakombinowałem z formatem ramki.<br/>
Poprawny format ramki:
<pre>@s = unpack("H6 H2 H6 H12 N (H2n/a*)*", $ramka);</pre>
No i sam scanner:
<pre>#!/usr/bin/perl
###############################################################################
#
# scan-ubiquiti.pl v2.1.0
#
# scan utility for ubiquiti
#
# 2012-08-24
# dodano rozpoznawanie kodow hardware'u: 'NS3','B2N','BS2'
#
# 2012-08-22
# poprawiono parsowanie odbieranego pakietu
# poprawiono parsowanie wersji software
#
# 2011-06-11
# przepisano engine na klasyczne sockety
#
# mindc.net
# 2011-03-20
###############################################################################
use strict;
use warnings;
use Socket;
use Time::HiRes qw(gettimeofday);
print "scan-ubiquiti.pl v2.0.0
hw ip board sw uptime name ssid
--------------------------------------------------------------------------------------------------------
";
my %dev;
open my $ph, "-|","ip a";
while ( <$ph> ) {
$dev{$2} = $1 if m@\s(\S+)/\d+\s.*(eth\d+)@;
}
close $ph;
my $data = {};
foreach my $saddr ( values %dev ) {
my $socket;
socket($socket,PF_INET,SOCK_DGRAM,17);
setsockopt($socket, SOL_SOCKET, SO_BROADCAST, 1 );
my $sin = sockaddr_in(50122,inet_aton($saddr));
bind($socket,$sin);
my $sout = sockaddr_in(10001,INADDR_BROADCAST);
send($socket,pack("H8","01000000"),0,$sout);
send($socket,pack("H8","01000000"),0,$sout);
send($socket,pack("H8","01000000"),0,$sout);
close $socket;
}
my $socket;
socket($socket,PF_INET,SOCK_DGRAM,17) or die "socket error - $!";
my $sin = sockaddr_in(50122,INADDR_ANY);
bind($socket,$sin);
setsockopt($socket, SOL_SOCKET, SO_BROADCAST, 0 );
my $rin = "";
vec($rin,fileno($socket),1) = 1;
my $end = gettimeofday() + 3;
my $timeout = $end - gettimeofday();
my $i = 0;
while ( select(my $rout = $rin,undef,undef,$timeout) ) {
$timeout = $end - gettimeofday();
my $rtime = "";
my $his = recv($socket,$rtime,1500,0) || die "recv: $!";
my ($port,$hisaddr) = sockaddr_in($his);
next if length($rtime) < 8; #skip self
my $o = ubiquiti_header(inet_ntoa($hisaddr),$rtime);
if ( not exists($data->{$o->{mac}})) {
my $sw = parse_sw($o->{sw});
printf("%3d. %17s %-16s %-16s %-6s %6s %-32s %s\n",
++$i,
$o->{mac} || '',
$o->{ip} || '',
models($o->{board}) || '',
$sw->{sw_version} || '',
sec2human($o->{uptime}) || '',
$o->{name} || '',
$o->{ssid} || ''
);
}
$data->{$o->{mac}}++;
}
close $socket;
print "\n" if keys %$data;
exit;
sub ubiquiti_header {
my $ip = shift;
my $frame = shift;
my $template = "H6 H2 H6 H12 N (H2n/a*)*";
my @header = unpack($template,$frame);
my $signature = shift @header;
return undef if $signature ne '010000';
my $t = shift @header;
shift @header;
my $mac = shift @header;
shift @header;
my $out = {};
@{$out}{qw(ip mac sw board key uptime ssid)} = ($ip,'','','','',0,'');
for ( my $i = 0; $i < @header ; $i += 2 ) {
my $type = $header[$i];
my $value = $header[$i+1];
$out->{sw} = $value if $type eq '03';
$out->{board} = $value if $type eq '0c';
$out->{name} = $value if $type eq '0b';
$out->{uptime} = unpack("N",$value) if $type eq '0a';
$out->{ssid} = $value if $type eq '0d';
}
$out->{mac} = uc join(":",unpack("(H2)6",pack("H*",$mac)));
$out->{frame} = $frame;
$out->{structure} = \@header;
return $out;
}
sub sec2human {
my $sec = shift;
return "" if $sec <= 0;
my $w = int($sec / 60 / 60 / 24 / 7);
my $d = int($sec / 60 / 60 / 24 % 7);
my $h = int($sec / 60 / 60 % 24);
my $m = int($sec / 60 % 60);
my $s = int($sec % 60);
if ( $w ) {
return sprintf("%dw%dd",$w,$d);
} elsif ( $d ) {
return sprintf("%dd%dh",$d,$h);
} elsif ( $h ) {
return sprintf("%dh%dm",$h,$m);
} elsif ( $m ) {
return sprintf("%dm%ds",$m,$s);
} else {
return "${s}s";
}
}
sub parse_sw {
my $sw = shift;
return {} unless $sw;
my @d = $sw =~ m/(\S{2,3})\.(ar\d+)\.v(\S+)\.(\d{4,5})\.(\d{6})\.(\d{4})/;
my $out = {
board => $d[0] || '',
chipset => uc $d[1] || '',
sw_version => $d[2],
build => $d[3] || '',
date => $d[4] || '',
unkn => $d[5] || ''
};
return $out;
}
sub models {
my $m = shift;
return 'NanoBridge M5' if $m eq 'NB5';
return 'WispStation5' if $m eq 'MS5';
return 'Rocket M5' if $m eq 'R5N';
return 'AirGrid M5' if $m eq 'AG5';
return 'NanoStation M3' if $m eq 'NS3';
return 'Bullet M2' if $m eq 'B2N';
return 'Bullet 2' if $m eq 'BS2';
return $m;
};
</pre>
Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-7801880320917397352012-04-11T11:32:00.000+02:002012-04-12T17:04:10.998+02:00Uruchamianie aplikacji w przeglądarce...<b>...czyli rejestrowanie własnego protokołu URL</b>
<p>Kilka razy podchodziłem do tego problemu. A to kombinowałem z zakręconym JavaScriptem (bezskutecznie), a to z pluginem do Firefoxa (z powodzeniem). Aż trafiłem na artykuł o rejestrowaniu własnych protokołów, tak jak wbudowany <code>http://</code></p>
<p>Aby przeglądarka rozpoznawała wywołanie typu <code>winbox:192.168.88.1;admin;admin;</code> należy ten protokół zarejestrować w systemie.<br/>
Osobiście potrzebowałem kilku takich protokołów, przygotowałem mały zestaw skrypt+aplikacja aby ten proces zautomatyzować.</p>
<p>Plik konfiguracyjny <code>url_launcher.config</code>:<br/><em>(Nazwa pliku jest ważna, na sztywno wpisana w aplikacji <code>url_launcher.exe</code>)</em></p>
<pre>
winbox;c:\bin\winbox.exe
putty;C:\BIN\putty.exe
quake;d:\games\Quake III Arena\quake3.exe
</pre>
<p>Pierwsza pozycja to nazwa protokołu, druga pozycja (oddzielona średnikiem) to ścieżka do pliku wykonywalnego obsługującego nasz protokół. Odpowiednie wpisy do rejestru wykonuje poniższy skrypt, wpisy są uzależnione od wpisów w pliku konfiguracyjnym.</p>
Skrypt <code>url_launcher.cmd</code>
<pre>
@echo off
set URL_LAUNCHER_PATH=%~dp0
set URL_LAUNCHER_PATH=%URL_LAUNCHER_PATH:\=\\%
echo Windows Registry Editor Version 5.00 > url_launcher.temp.reg
FOR /F "eol= tokens=1,2 delims=;" %%I in (url_launcher.config) do (
(
echo [HKEY_CLASSES_ROOT\%%I]
echo @="Winbox URI"
echo "URL Protocol"=""
echo [HKEY_CLASSES_ROOT\%%I\DefaultIcon]
echo @="\"%%J\",0"
echo [HKEY_CLASSES_ROOT\%%I\shell]
echo @="open"
echo [HKEY_CLASSES_ROOT\%%I\shell\open]
echo [HKEY_CLASSES_ROOT\%%I\shell\open\command]
echo @="\"%URL_LAUNCHER_PATH%url_launcher.exe\" \"%%1\""
) >> url_launcher.temp.reg
)
regedit /s url_launcher.temp.reg
del url_launcher.temp.reg
</pre>
<p>Do tego wszystkiego, potrzebny jest mały programik, który obrobi dane wejściowe i wywoła nam aplikację docelową <code><a href="http://zeus.mindc.net/files/url_launcher.exe">url_launcher.exe</a></code></p>
<p>Wracając do naszego protokołu <code>winbox:192.168.88.1;admin;admin</code>, po wpisaniu go w pasku adresu przeglądarki i uruchomieniu, zostanie uruchomiony program z parametrami <code>c:\bin\winbox.exe 192.168.88.1 admin admin</code>. Analogicznie z <code>putty:8.8.8.8;-l;root</code> zostanie uruchomiony <code>c:\bin\putty.exe 8.8.8.8 -l root</code></p>
<p>Aby wszystko zadziałało bezproblemowo, wszystkie pliki powinny znajdować się w tym samym katalogu.</p>
<p>I na zakończenie: to rozwiązanie jest uniwersalne, działa w każdej przeglądarce.</p>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-44362864654294524882012-04-05T19:34:00.000+02:002012-12-19T13:56:01.725+01:00Speedtest.net Mini - automatyczna aktualizacjaCzasami zdarzało się, że wchodząc na mój własny speedtest okazywało się, że jest nieaktualny... czasami taki nieaktualny wisiał ponad miesiąc...
<br/>
Napisałem więc prościusieńki skrypt w BASHu który robi to za mnie
<pre>
#!/bin/bash
cd <pełna_ścieżka_do_katalogu_z_twoim_speedtest.net_mini>
if ! wget -N http://c.speedtest.net/mini/mini.zip 2>&1 | grep -q "not retrieving";then
unzip -o mini.zip
cp -fR ./mini/* .
fi
</pre>
Uruchamiamy co jakiś czas z <code>crona</code> i zapominamy o pilnowaniu i aktualizowaniu naszego <a href="http://www.speedtest.net/mini.php">Speedtest.net Mini</a>.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-63543852259783077182012-03-06T19:07:00.005+01:002012-04-28T13:15:32.926+02:00Clean DriveTak sobie przypomniałem o pewnej bardzo prostej komendzie, którą można czyścić dyski ze zbędnych śmieci (chodzi o zajęte sektory po usuniętych plikach). Bardzo przydatne przy tworzeniu obrazów dysków/partycji w systemach plików nie obsługiwanych przez Wasz program do archiwizacji (tryb 'sektor po sektorze'). A wszystko po to, aby zminimalizować rozmiar skompresowanego archiwum...
<pre>dd if=/dev/zero of=/0bits bs=20M;rm -f /0bits
dd if=/dev/zero of=/home/0bits bs=20M;rm -f /home/0bits
dd if=/dev/zero of=/var/0bits bs=20M;rm -f /var/0bits
dd if=/dev/zero of=/usr/0bits bs=20M;rm -f /usr/0bits
dd if=/dev/zero of=/tmp/0bits bs=20M;rm -f /tmp/0bits
</pre>
Oczywiście parametry wywołań będą różnić się od ilości i miejsca montowań partycji.
<br/>
Przy okazji zmierzymy prędkość zapisu na danej partycji :)Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-38748703805426843512011-08-10T13:37:00.017+02:002011-08-12T15:34:05.356+02:00Szablon XSL - słownie złotychPrzy okazji uruchamiania systemu generującego PDFy z fakturami, potrzebowałem czegoś, co zamieni kwoty przedstawione za pomocą liczb na odpowiadający im opis słowny. Tak powstał ten szablon XSL, gotowy do dołączenia w projektach.<br/>
Pierwowzorem był znaleziony w necie, pewien algorytm napisany w C#, który to w międzyczasie przerobiłem na Javascript (tego użyłem w innym projekcie związanym z PDF).<br/>I tak oto powstał ten szbalon.
<pre><xsl:template name="get-gr">
<xsl:param name="amount"/>
<xsl:variable name="a1" select="floor($amount)"/>
<xsl:variable name="len" select="string-length($a1)"/>
<xsl:variable name="a2" select="substring($a1,$len,1)"/>
<xsl:choose>
<xsl:when test="$a1 = 1"><xsl:value-of select="document('amount-in-words.xml')/amount-in-words/grosze[1]"/></xsl:when>
<xsl:when test="$a2 > 1 and $a2 < 5"><xsl:value-of select="document('amount-in-words.xml')/amount-in-words/grosze[2]"/></xsl:when>
<xsl:otherwise><xsl:value-of select="document('amount-in-words.xml')/amount-in-words/grosze[3]"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="get-zl">
<xsl:param name="amount"/>
<xsl:variable name="a1" select="floor($amount)"/>
<xsl:variable name="len" select="string-length($a1)"/>
<xsl:variable name="a2" select="substring($a1,$len,1)"/>
<xsl:choose>
<xsl:when test="$a1 = 1"><xsl:value-of select="document('amount-in-words.xml')/amount-in-words/zlote[1]"/></xsl:when>
<xsl:when test="$a2 > 1 and $a2 < 5"><xsl:value-of select="document('amount-in-words.xml')/amount-in-words/zlote[2]"/></xsl:when>
<xsl:otherwise><xsl:value-of select="document('amount-in-words.xml')/amount-in-words/zlote[3]"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="get-words">
<xsl:param name="amount"/>
<xsl:variable name="zl" select="floor($amount)"/>
<xsl:variable name="len" select="string-length($zl)"/>
<xsl:if test="$len > 6">
<xsl:variable name="million2" select="substring($zl,$len -6,1)"/>
<xsl:variable name="million">
<xsl:if test="$len > 8"><xsl:value-of select="substring($zl,$len -8,1)"/></xsl:if>
<xsl:if test="$len > 7"><xsl:value-of select="substring($zl,$len -7,1)"/></xsl:if>
<xsl:value-of select="substring($zl,$len -6,1)"/>
</xsl:variable>
<xsl:if test="$million > 1">
<xsl:call-template name="get-words">
<xsl:with-param name="amount" select="$million"/>
</xsl:call-template>
</xsl:if>
<xsl:choose>
<xsl:when test="$million = 1">
<xsl:value-of select="document('amount-in-words.xml')//millions[1]"/>
</xsl:when>
<xsl:when test="$million > 1 and $million < 5">
<xsl:value-of select="document('amount-in-words.xml')//millions[2]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document('amount-in-words.xml')//millions[3]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="$len > 3">
<xsl:variable name="thousend2" select="substring($zl,$len -3,1)"/>
<xsl:variable name="thousend">
<xsl:if test="$len > 5"><xsl:value-of select="substring($zl,$len -5,1)"/></xsl:if>
<xsl:if test="$len > 4"><xsl:value-of select="substring($zl,$len -4,1)"/></xsl:if>
<xsl:value-of select="substring($zl,$len -3,1)"/>
</xsl:variable>
<xsl:if test="$thousend > 1">
<xsl:call-template name="get-words">
<xsl:with-param name="amount" select="$thousend"/>
</xsl:call-template>
</xsl:if>
<xsl:choose>
<xsl:when test="$thousend = 1">
<xsl:value-of select="document('amount-in-words.xml')//thousends[1]"/>
</xsl:when>
<xsl:when test="$thousend2 > 1 and $thousend2 < 5">
<xsl:value-of select="document('amount-in-words.xml')//thousends[2]"/>
</xsl:when>
<xsl:when test="$thousend = '000' and $len > 6">
<xsl:text></xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document('amount-in-words.xml')//thousends[3]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="$len > 2">
<xsl:if test="substring($zl,$len -2,1) != 0">
<xsl:value-of select="document('amount-in-words.xml')//hundrets[substring($zl,$len -2,1) + 1]"/>
</xsl:if>
</xsl:if>
<xsl:if test="$len > 0">
<xsl:variable name="to99">
<xsl:choose>
<xsl:when test="$len = 1">
<xsl:value-of select="substring($zl,$len,1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($zl,$len -1,2)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$to99 < 20">
<xsl:choose>
<xsl:when test="substring($to99,1,1) = 0">
<xsl:if test="substring($to99,2,1) != 0">
<xsl:value-of select="document('amount-in-words.xml')//units[substring($to99,2,1) + 1]"/>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$to99 != 0">
<xsl:value-of select="document('amount-in-words.xml')//units[$to99 + 1]"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document('amount-in-words.xml')//tens[substring($to99,1,1)+1]"/>
<xsl:if test="substring($to99,2,2) != 0">
<xsl:value-of select="document('amount-in-words.xml')//units[substring($to99,2,2) + 1]"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="$zl = 0">
<xsl:value-of select="document('amount-in-words.xml')//units[1]"/>
</xsl:if>
</xsl:template>
<xsl:template name="amount-in-words">
<xsl:param name="amount"/>
<xsl:call-template name="get-words"><xsl:with-param name="amount" select="$amount"/></xsl:call-template>
<xsl:call-template name="get-zl"><xsl:with-param name="amount" select="$amount"/></xsl:call-template>
<xsl:call-template name="get-words"><xsl:with-param name="amount" select="round(($amount - floor($amount))*100)"/></xsl:call-template>
<xsl:call-template name="get-gr"><xsl:with-param name="amount" select="round(($amount - floor($amount))*100)"/></xsl:call-template>
</xsl:template></pre>Powyższy fragment kody należy umieścić w dowolnym miejscu istniejącego szablonu. Dodatkowo w katalogu z szablonem, należy umieścić poniższy plik o nazwie <code>amount-in-words.xml</code>:<pre><?xml version="1.0" encoding="UTF-8"?>
<amount-in-words>
<grosze>grosz </grosze>
<grosze>grosze </grosze>
<grosze>groszy </grosze>
<zlote>złoty </zlote>
<zlote>złote </zlote>
<zlote>złotych </zlote>
<units>zero </units>
<units>jeden </units>
<units>dwa </units>
<units>trzy </units>
<units>cztery </units>
<units>pięć </units>
<units>sześć </units>
<units>siedem </units>
<units>osiem </units>
<units>dziewięć </units>
<units>dziesięć </units>
<units>jedenaście </units>
<units>dwanaście </units>
<units>trzynaście </units>
<units>czternaście </units>
<units>piętnaście </units>
<units>szesnaście </units>
<units>siedemnaście </units>
<units>osiemnaście </units>
<units>dziewiętnaście </units>
<tens></tens>
<tens>dziesięć </tens>
<tens>dwadzieścia </tens>
<tens>trzydzieści </tens>
<tens>czterdzieści </tens>
<tens>pięćdziesiąt </tens>
<tens>sześćdziesiąt </tens>
<tens>siedemdziesiąt </tens>
<tens>osiemdziesiąt </tens>
<tens>dziewięćdziesiąt </tens>
<hundrets></hundrets>
<hundrets>sto </hundrets>
<hundrets>dwieście </hundrets>
<hundrets>trzysta </hundrets>
<hundrets>czterysta </hundrets>
<hundrets>pięćset </hundrets>
<hundrets>sześćset </hundrets>
<hundrets>siedemset </hundrets>
<hundrets>osiemset </hundrets>
<hundrets>dziewięćset </hundrets>
<thousends>tysiąc </thousends>
<thousends>tysiące </thousends>
<thousends>tysięcy </thousends>
<millions>milion </millions>
<millions>miliony </millions>
<millions>milionów </millions>
</amount-in-words> </pre>
Wywołanie jest proste, polega na wstawieniu poniższego fragmentu w interesującym nas miejscu szblonu:<pre><xsl:call-template name="amount-in-words">
<xsl:with-param name="amount" select="value"/>
</xsl:call-template></pre>Jak na razie, u mnie ma to status beta, jeśli ktoś znajdzie jakieś błędy, zaproponuje poprawki, zapraszam do dyskusji.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-35612124927000860522011-07-05T15:44:00.013+02:002011-08-14T16:23:46.118+02:00cwRsync portableCzęsto używam <code>rsync</code> do robienia backupów albo do synchronizowania zawartości folderów na wielu serwerach. Ostatnio postanowiłem, że kupię sobie dysk przenośny o dużej pojemności i wrzucę tam wszystkie najważniejsze swoje rzeczy. Chciałem mieć możliwość robienia tego z dowolnego miejsca przez net, więc pomyślałem o <code>rsync</code>.<br/>
<br/>
Wszystko chciałem uruchamiać pod Windows, na dowolnym kompie do którego się podepnę. Stworzyłem prostą strukturę katalogów w głównym folderze dysku:<pre>\bin
\backup</pre>Zawartość z katalogu <code>bin</code> z folderu instalacyjnego <b>cwRsync</b> wrzuciłem do katalogu <code>bin</code> na dysku przenośnym.<br/>
<br/>
Dorzuciłem też plik <code>cwrsync.cmd </code> do głównego katalogu. Poniżej zawartość pliku:<pre>@echo off
setlocal
set CWRSYNCHOME=%~d0\bin
set CYGWIN=nontsec
set HOME=%HOMEDRIVE%%HOMEPATH%
set PATH=%~d0\bin;%PATH%
cygpath -a backup > backup.d
set /p BACKUP= < backup.d
del backup.d
rsync -rtlv --compress <em>user</em>@<em>host</em>::<em>moduł</em> %BACKUP%/ < %~d0\<em>plik_z_hasłem</em></pre>
Problem z <code>rsync</code> polegał na tym, że ścieżka docelowa musi być absolutną ścieżką w formacie <code>cygwin</code>, np.: <code style="white-space:nowrap">/cygdrive/h/backup</code>. Wszelkie próby z relatywną ścieżką zawodziły.<br/>
Wykorzystałem także możliwość prostej autoryzacji w <code>rsync</code>, jedynym sposobem przekazania hasła, było proste przekierowanie go z zewnętrznego pliku.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-10638655036252765802011-06-14T15:33:00.045+02:002017-08-05T23:10:19.277+02:00EVE Online i Skill Training QueueZnowu się nudziłem i napisałem sobie mały projekt w PHP, który informuje mnie o kolejce skilli w <a href="http://www.eveonline.com/">EVE Online</a>, bez potrzeby logowania się do gry.<br/>
<iframe style="width:100%;height:150px;border:none;background-color:silver" src="http://tools.matcom.com.pl/eve.php"></iframe>
Jeśli ktoś będzie zainteresowany źródłem, dorzucę do bloga.<br/><br/>
Jeszcze pomyślę o "oklejeniu" tego jakimś javascriptem, aby dane wyglądały jeszcze bardziej "na bieżąco".Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com4tag:blogger.com,1999:blog-5883011934720163442.post-76730707969709912752011-06-11T22:56:00.018+02:002011-07-15T14:25:54.993+02:00Ubiquiti cz.2Dzisiaj rzutem na taśmę skaner do <b>Ubiquiti</b>. W odróżnieniu od Mikrotika, Ubiquiti odpowiada na adres z którego zostało wysłane zapytanie. Ale w tym skrypcie nasłuchujemy na dowolnym adresie, tak jak w skanerze dla Mikrotików.
No i miały być szczegóły techniczne. Skaner rozsyła z portu 50122 na port 10001 paczkę <code>0x01000000</code> po broadcaście. Urządzenie wysyła odpowiedź na port 50122.
Trochę dłubaniny było przy zmiennym formacie ramki ale dość łatwo było ominąć ten problem. Pierwszy rodzaj ramki:<pre>@s = unpack("H6H2H6H12NH6H12H8(H2n/a*)*", $ramka);
$s[0] sygnatura (0x010000)
$s[1] nie pamiętam :)
$s[2] ??
$s[3] adres MAC
$s[4] ??
$s[5] ??
$s[6] ??
$s[7] ??
(
$s[8] typ pola
X długość łańcucha (automatycznie wchłaniane przez unpack)
$s[9] łańcuch
)
...</pre>Drugi rodzaj ramki:<pre>@s = unpack("H6H2H6H12NH6H12H14(H2n/a*)*", $ramka);
$s[0] sygnatura (0x010000)
$s[1] nie pamiętam :)
$s[2] ??
$s[3] adres MAC
$s[4] ??
$s[5] ??
$s[6] ??
$s[7] ?? (tutaj długość jest większa o 3 bajty)
(
$s[8] typ pola
X długość łańcucha (automatycznie wchłaniane przez unpack)
$s[9] łańcuch
)
...</pre>Zidentyfikowane typy pól:<pre>0x03 - wersja softu
0x0a - uptime
0x0b - nadana nazwa dla urządzenia
0x0c - model urządzenia
0x0d - SSID do którego jest podpięte urządzenie gdy pracuje w trybie klienta</pre>No i skrypt:<pre>#!/usr/bin/perl
###############################################################################
#
# scan-ubiquiti.pl v1.2.0
#
# scan utility for ubiquiti
#
# 2011-06-11
# przepisano engine na klasyczne sockety
#
# mindc.net
# 2011-03-20
###############################################################################
use strict;
use warnings;
use Socket;
use Time::HiRes qw(gettimeofday);
print "scan-ubiquiti.pl v1.2.0
hw ip board sw uptime name ssid
--------------------------------------------------------------------------------------------------------
";
my %dev;
open my $ph, "-|","ip a";
while ( <$ph> ) {
$dev{$2} = $1 if m@\s(\S+)/\d+\s.*(eth\d+)@;
}
close $ph;
my $data = {};
foreach my $saddr ( values %dev ) {
my $socket;
socket($socket,PF_INET,SOCK_DGRAM,17);
setsockopt($socket, SOL_SOCKET, SO_BROADCAST, 1 );
my $sin = sockaddr_in(50122,inet_aton($saddr));
bind($socket,$sin);
my $sout = sockaddr_in(10001,INADDR_BROADCAST);
send($socket,pack("H8","01000000"),0,$sout);
send($socket,pack("H8","01000000"),0,$sout);
send($socket,pack("H8","01000000"),0,$sout);
close $socket;
}
my $socket;
socket($socket,PF_INET,SOCK_DGRAM,17) or die "socket error - $!";
my $sin = sockaddr_in(50122,INADDR_ANY);
bind($socket,$sin);
my $rin = "";
vec($rin,fileno($socket),1) = 1;
my $end = gettimeofday() + 3;
my $timeout = $end - gettimeofday();
my $i = 0;
while ( select(my $rout = $rin,undef,undef,$timeout) ) {
$timeout = $end - gettimeofday();
my $rtime = "";
my $his = recv($socket,$rtime,1500,0) || die "recv: $!";
my ($port,$hisaddr) = sockaddr_in($his);
next if length($rtime) < 8; #skip self
my $o = ubiquiti_header(inet_ntoa($hisaddr),$rtime);
if ( not exists($data->{$o->{mac}})) {
my $sw = parse_sw($o->{sw});
printf("%2d. %17s %-16s %-16s %-4s %6s %-24s %s\n",
++$i,
$o->{mac},
$o->{ip},
models($o->{board}),
$sw->{sw_version},
sec2human($o->{uptime}),
$o->{name},
$o->{ssid}
);
}
$data->{$o->{mac}}++;
}
close $socket;
print "\n" if keys %$data;
exit;
sub ubiquiti_header {
my $ip = shift;
my $frame = shift;
my $template = "H6 H2 H6 H12 N H6 H12 H8 (H2n/a*)*";
my @header = unpack($template,$frame);
my $signature = shift @header;
return undef if $signature ne '010000';
my $t = shift @header;
shift @header;
my $mac = shift @header;
shift @header;
shift @header;
shift @header;
shift @header;
if ( $header[0] ne '01' ) {
$template = "H6 H2 H6 H12 N H6 H12 H14 (H2n/a*)*";
@header = unpack($template, $frame);
$signature = shift @header;
return undef if $signature ne '010000';
$t = shift @header;
shift @header;
$mac = shift @header;
shift @header;
shift @header;
shift @header;
shift @header;
}
my $out = {};
@{$out}{qw(ip mac sw board key uptime ssid)} = ($ip,'','','','',0,'');
for ( my $i = 0; $i < @header ; $i += 2 ) {
my $type = $header[$i];
my $value = $header[$i+1];
$out->{sw} = $value if $type eq '03';
$out->{board} = $value if $type eq '0c';
$out->{name} = $value if $type eq '0b';
$out->{uptime} = unpack("N",$value) if $type eq '0a';
$out->{ssid} = $value if $type eq '0d';
}
$out->{mac} = uc join(":",unpack("(H2)6",pack("H*",$mac)));
$out->{frame} = $frame;
$out->{structure} = \@header;
return $out;
}
sub sec2human {
my $sec = shift;
return "" if $sec <= 0;
my $w = int($sec / 60 / 60 / 24 / 7);
my $d = int($sec / 60 / 60 / 24 % 7);
my $h = int($sec / 60 / 60 % 24);
my $m = int($sec / 60 % 60);
my $s = int($sec % 60);
if ( $w ) {
return sprintf("%dw%dd",$w,$d);
} elsif ( $d ) {
return sprintf("%dd%dh",$d,$h);
} elsif ( $h ) {
return sprintf("%dh%dm",$h,$m);
} elsif ( $m ) {
return sprintf("%dm%ds",$m,$s);
} else {
return "${s}s";
}
}
sub parse_sw {
my $sw = shift;
return {} unless $sw;
my @s = split /\./,$sw;
$s[2] = $s[2] || '';
$s[3] = $s[3] || '';
$s[2] =~ s/v//g;
my $out = {
board => $s[0] || '',
chipset => uc $s[1] || '',
build => $s[4] || '',
date => $s[5] || '',
unkn => $s[6] || ''
};
$out->{sw_version} = $s[2].".".$s[3] if $s[2] && $s[3];
return $out;
}
sub models {
my $m = shift;
return 'NanoBridgeM' if $m eq 'NB5';
return 'WISPStation5' if $m eq 'MS5';
return 'RocketM' if $m eq 'R5N';
return 'AirGridM5' if $m eq 'AG5';
return $m;
};
</pre>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-48502882925647491842011-06-11T22:12:00.005+02:002012-10-08T10:01:04.337+02:00MNDP cz.4Zaczął mnie irytować ten <code>tcpdump</code>. Ogarnąłem się trochę i przepisałem część kodu w zwykłych socketach.
<pre>#!/usr/bin/perl
###############################################################################
#
# scan-mikrotik.pl v2.8.0
#
# scan utility for mikrotik
#
# 2011-06-11
# przepisano engine na klasyczne sockety
#
# 2011-03-27
# dodano uptime
#
# mindc.net
# 2011-03-20
###############################################################################
use strict;
use warnings;
use Socket;
use Time::HiRes qw(gettimeofday);
print "scan-mikrotik.pl v2.8.0
hw ip board sw uptime identity
--------------------------------------------------------------------------------
";
my %dev;
open my $ph, "-|","ip a";
while ( <$ph> ) {
$dev{$2} = $1 if m@\s(\S+)/\d+\s.*(eth\d+)@;
}
close $ph;
my $data = {};
foreach my $saddr ( values %dev ) {
my $socket;
socket($socket,PF_INET,SOCK_DGRAM,17);
setsockopt($socket, SOL_SOCKET, SO_BROADCAST, 1 );
my $sin = sockaddr_in(5678,inet_aton($saddr));
bind($socket,$sin);
my $sout = sockaddr_in(5678,INADDR_BROADCAST);
send($socket,pack("H8",0),0,$sout);
send($socket,pack("H8",0),0,$sout);
send($socket,pack("H8",0),0,$sout);
close $socket;
}
my $socket;
socket($socket,PF_INET,SOCK_DGRAM,17) or die "socket error - $!";
my $sin = sockaddr_in(5678,INADDR_ANY);
bind($socket,$sin);
my $rin = "";
vec($rin,fileno($socket),1) = 1;
my $end = gettimeofday() + 3;
my $timeout = $end - gettimeofday();
my $i = 0;
while ( select(my $rout = $rin,undef,undef,$timeout) ) {
$timeout = $end - gettimeofday();
my $rtime = "";
my $his = recv($socket,$rtime,1500,0) || die "recv: $!";
my ($port,$hisaddr) = sockaddr_in($his);
next if length($rtime) < 5; #skip self
my $o = mikrotik_header(inet_ntoa($hisaddr),$rtime);
if ( not exists($data->{$o->{mac}})) {
printf("%2d. %17s %-16s %-10s %-7s %6s %s\n",
++$i,
$o->{mac},
$o->{ip},
$o->{board},
$o->{sw},
sec2human($o->{uptime}),
$o->{identity}
);
}
$data->{$o->{mac}}++;
}
close $socket;
print "\n" if keys %$data;
exit;
sub mikrotik_header {
my $ip = shift;
my $buffer = shift;
my @header = unpack("H2H2S(H4n/a*)*", $buffer);
shift @header; #?
shift @header; #?
shift @header; #age?
my $out = {};
@{$out}{qw(ip mac identity vendor sw board key uptime)} = ($ip,'','','','','','',0);
for ( my $i = 0; $i < @header ; $i += 2 ) {
my $type = $header[$i];
my $value = $header[$i+1];
$out->{mac} = uc join(":",unpack("(H2)6",$value)) if $type eq '0001';
$out->{identity} = $value if $type eq '0005';
$out->{vendor} = $value if $type eq '0008';
$out->{sw} = $value if $type eq '0007';
$out->{board} = $value if $type eq '000c';
$out->{key} = $value if $type eq '000b';
$out->{uptime} = unpack("L",$value) if $type eq '000a';
# $out->{unknown2} = $value if $type eq '000d';
}
return $out;
}
sub sec2human {
my $sec = shift;
return "" if $sec <= 0;
my $w = int($sec / 60 / 60 / 24 / 7);
my $d = int($sec / 60 / 60 / 24 % 7);
my $h = int($sec / 60 / 60 % 24);
my $m = int($sec / 60 % 60);
my $s = int($sec % 60);
if ( $w ) {
return sprintf("%dw%dd",$w,$d);
} elsif ( $d ) {
return sprintf("%dd%dh",$d,$h);
} elsif ( $h ) {
return sprintf("%dh%dm",$h,$m);
} elsif ( $m ) {
return sprintf("%dm%ds",$m,$s);
} else {
return "${s}s";
}
}</pre>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-81716773631833119792011-05-20T14:55:00.015+02:002011-05-26T14:15:01.981+02:00APE (Ajax Push Engine) i SSLPo długich poszukiwaniach rozwiązania tego problemu... utknąłem...
W jednym miejscu piszą, że to działa tylko ze starą wersją <code>stunnel</code> (u mnie to nie działało) gdzie indziej robią sztuczki z przekierowaniami na Apachu (siedzę od jakiegoś czasu na <code>lighttpd</code> i nie wnikałem)...
Po wnikliwej analizie co się dzieje w momencie negocjacji przez <code>stunnel</code> doszedłem, że chodzi o coś z timeoutami... Jedna z opcji wydawała się obiecująca...
Poniżej działający bezproblemowo z APE, <code>stunnel.conf</code><pre>output = /var/log/stunnel.log
pid = /var/run/stunnel.pid
foreground = no
[ape]
<b>TIMEOUTclose = 0</b>
cert = <ścieżka do certyfikatu>
accept = <host na którym nasłuchujemy>:4443
connect = <ape serwer>:6969</pre>Pogrubiłem opcję, która wszystko "naprawiła". Należy pamiętać także o zmianach w pliku <code>config.js</code><pre>APE.Config.baseUrl = '<serwer z którego pobieramy biblioteki>'; //APE JSF
APE.Config.domain = '<domena jak w pliku ape.conf>';
APE.Config.server = '<ape serwer>:<b>4443</b>'; //APE server URL
<b>APE.Config.secure = true;</b></pre>I możemy się cieszyć APE z SSLem. Należy tylko pamiętać o "wildcardowych" certyfikatach...Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-86585114697528202952011-05-05T18:08:00.011+02:002012-05-04T13:31:11.971+02:00Google Maps API v2 + zumi.plDzisiaj wracam do tematu map z <a href="http://www.zumi.pl">zumi.pl</a>. Ten mały projekt powstał jeszcze za czasów, gdy w Google Maps, zdjęcia satelitarne były mało szczegółowe. Wpadłem więc na pomysł, aby połączyć Google Maps API z kafelkami map z zumi.pl.
Pierwszy był skrypt w perlu który... ściągał wszystkie kafelki z zumi.pl, dla każdego przybliżenia. Ale po ściągnięciu ich wszystkich stwierdziłem, że wykorzystanie tego jest bezcelowe.
Drugim podejściem było połączenie właśnie z API Google, które to już trochę poznałem i wykorzystywałem do własnych celów. Problemem z połączeniem tych dwóch map polegał na tym, że odwzorowanie map, a raczej "pocięcie" całej mapy na kafelki znacznie różniło się w obu tych przypadkach.
Kluczem do sukcesu było poznanie algorytmu kafelkowania map w zumi.pl.
Myślałem, że wyjaśnię co z czego wynika, ale nie pamiętam już za wiele. Po prostu trzeba zajrzeć w źródła :)
<iframe style="width:100%;height:560px;border:none" src="http://static.mindc.net/mapv2.html"></iframe>
Stronka ta, to okrojona wersja czegoś co używam na co dzień, więc mogą tam być jeszcze jakieś niepotrzebne "śmieci".
Kluczowym elementem jest funkcja <code>getTileUrl</code>, która na podstawie podanej szerokości i długości geograficznej oraz przybliżenia, wylicza nam, który kafelek ma być pobrany z serwera zumi.pl. Reszta to funkcje wyświetlające to wszystko.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-36391399911691429972011-04-20T17:32:00.014+02:002011-08-10T13:52:14.169+02:00Apache FOPZnowu wróciłem do FOP'a. Pomyślałem sobie, że jak znajdę sposób na obliczenie szerokości kolumn w tabeli na podstawie znajdujących się tam danych i ustawię tą szerokość na sztywno, to będzie można spokojnie obejść problem <code style="white-space:nowrap">table-layout="fixed"</code>.
W PHP mamy do dyspozycji funkcję <code>imagettfbbox</code>, dzięki której można wyliczyć szerokość tekstu przy zastosowaniu określonej czcionki. Najprościej można to zrobić tak:<pre class="prettyprint">function get_text_width($font,$font_size,$text) {
$box = imagettfbbox($font_size,0,$font,$text);
return $box[4];
}</pre>
Gdzie:
<code>$font</code> - ścieżka do użytej czcionki
<code>$font_size</code> - rozmiar czcionki dla której ma być wyliczona szerokość tekstu
<code>$text</code> - tekst dla którego wyliczymy szerokość.
Przed wygenerowanie właściwej tabeli w XSL-FO, wyliczam maksymalne szerokości dla danych z każdej kolumny i na tej podstawie generuję tagi <code><fo:table-column column-width="??"/></code>.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com2tag:blogger.com,1999:blog-5883011934720163442.post-20073664544482962172011-04-16T11:47:00.008+02:002012-10-08T10:01:25.237+02:00MNDP cz.3poniżej zamieszcza skrypt, skanujący za pomocą MNDP otoczenie sieciowe
<pre>#!/usr/bin/perl -w
###############################################################################
#
# scan-mikrotik.pl v2.6.0
#
# scan utility for mikrotik
#
# 2011-03-27
# dodano uptime
#
# 2011-03-20
# mindc.net
###############################################################################
use strict;
use IO::Socket;
use Data::Dumper;
use Time::HiRes qw( usleep );
$|=1;
my %links;
print "scan-mikrotik.pl v2.6.0
link hw ip board sw uptime identity
--------------------------------------------------------------------------------
wait for 3 sec...\r";
open my $ph, "-|","ip a";
while ( <$ph> ) {
$links{$2} = $1 if m@\s(\S+)/\d+\s.*(eth\d+)@;
}
close $ph;
foreach my $link ( keys %links ) {
unless ( fork ) {
my $socket = IO::Socket::INET->new(
Proto => 'UDP',
PeerPort => 5678,
PeerAddr => inet_ntoa(INADDR_BROADCAST),
LocalAddr => $links{$link},
Broadcast => 1,
Reuse => 1
) or die "cannot bind socket $!\n";
my $data = {};
eval {
my $out = {};
local $SIG{ALRM} = sub {
foreach ( sort keys %$data ) {
my $o = $data->{$_};
printf("%s %17s %-16s %-10s %-7s %6s %s\n",
$link,
$o->{mac},
$o->{ip},
$o->{board},
$o->{sw},
sec2human($o->{uptime}),
$o->{identity}
);
}
print "\n" if keys %$data;
exit;
};
alarm 3;
open (STDIN,"tcpdump -i $link -lnqxt -s 1024 src port 5678 and proto UDP 2>/dev/null |");
usleep(100000);
$socket->send(pack("H8",0));
usleep(100000);
$socket->send(pack("H8",0));
usleep(100000);
$socket->send(pack("H8",0));
close $socket;
my $buffer = '';
my $i = 0;
while (<>) {
s/IP \S+.5678 > \S+ UDP, length \d+.*//g;
s/0x\d\d\d\d://g;
s/\s+//g;
$buffer .= $_;
if ( $_ =~ /^$/ && $buffer ne '' ) {
$i++;
my $out = mikrotik_header($buffer);
$data->{$out->{mac}} = $out;
$buffer = '';
}
}
alarm 0;
};
exit;
}
}
1 while ( wait() != -1);
system "killall tcpdump";
exit;
sub mikrotik_header {
my $buffer = shift;
#ip #udp #mikrotik
my @header = unpack("H4nH8H8NN nnnH4 H2H2S(H4n/a*)*", pack("H*",$buffer));
#ip header
shift @header; #ip1
shift @header; #ip_lenght
shift @header; #ip2
shift @header; #ip3
my $ip = shift @header; #ip_src
shift @header; #ip_dst
#udp header
shift @header; #udp_src_port
shift @header; #udp_dst_port
shift @header; #udp_lenght
shift @header; #udp_checksum
shift @header; #?
shift @header; #?
shift @header; #age?
my $out = {};
$out->{mac} = '';
$out->{identity} = '';
$out->{vendor} = '';
$out->{sw} = '';
$out->{board} = '';
$out->{key} = '';
$out->{uptime} = 0;
$out->{ip} = join(".",unpack("C4",pack("N",$ip)));
for ( my $i = 0; $i < @header ; $i += 2 ) {
my $type = $header[$i];
my $value = $header[$i+1];
$out->{mac} = uc join(":",unpack("(H2)6",$value)) if $type eq '0001';
$out->{identity} = $value if $type eq '0005';
$out->{vendor} = $value if $type eq '0008';
$out->{sw} = $value if $type eq '0007';
$out->{board} = $value if $type eq '000c';
$out->{key} = $value if $type eq '000b';
$out->{uptime} = unpack("L",$value) if $type eq '000a';
# $out->{unknown2} = $value if $type eq '000d';
}
return $out;
}
sub sec2human {
my $sec = shift;
return "" if $sec <= 0;
my $w = int($sec / 60 / 60 / 24 / 7);
my $d = int($sec / 60 / 60 / 24 % 7);
my $h = int($sec / 60 / 60 % 24);
my $m = int($sec / 60 % 60);
my $s = int($sec % 60);
if ( $w ) {
return sprintf("%dw%dd",$w,$d);
} elsif ( $d ) {
return sprintf("%dd%dh",$d,$h);
} elsif ( $h ) {
return sprintf("%dh%dm",$h,$m);
} elsif ( $m ) {
return sprintf("%dm%ds",$m,$s);
} else {
return "${s}s";
}
}</pre>
Działanie jest proste. Skrypt wysyła na każdym z interfejsów zapytanie <code>0x00000000</code> i zaczyna nasłuchiwać na odpowiedź w formacie MNDP. Warunkiem działania skrytpu jest istnienie co najmniej jednego adresu IP na danym interfejsie.
Niezbyt eleganckie rozwiązanie z <code>killall tcpdump</code>, ale nie mogłem sobie z tym poradzić, gdy nie zamykam <code>STDIN</code>. A może by tak <code>select</code>.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-48733378433181135982011-04-13T15:21:00.006+02:002011-04-20T17:44:08.182+02:00Apache FOP vs. RenderX XEPNo to krótkie porównanie...
<a href="http://xmlgraphics.apache.org/fop/">Apache FOP</a> - totalny Open Source, można wykorzystać gdzie się chce i jak się chce. Ogromną zaletą FOP'a jest generowanie plików o minimalnym rozmiarze, prawdopodobnie dołącza do generowanego pliku wyłącznie fonty użyte w dokumencie. Ale niestety, nie można ustawić dla tabeli atrybutu <code>table-layout="auto"</code>, co przy generowaniu dynamicznych tabel, jest nie do przyjęcia.
<a href="http://www.renderx.com/">RenderX XEP</a> - zamknięte źródła, do użytku za free dostępna jedynie licencja personal. Na dole każdej strony w generowanym dokumencie, dołączana jest stopka RenderX z logiem. Do tego dołącza cały zastaw fontów do generowanego dokumentu co wiąże się z dość dużym nakładem na wielkość pliku. Ale... poprawnie interpretuje atrybut <code>table-layout="auto"</code>.
Tak więc, zdecydowałem się używać XEP'a ze względu na te tabele...Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-39555188425306314582011-04-07T13:10:00.011+02:002012-04-05T19:36:04.065+02:00FOP i fontyAby użyć dodatkowych fontów w Apache FOP, w pliku konfiguracyjnym w sekcji <code><fonts></code>, należy umieścić odpowiednie wpisy.
Poniżej zamieszczam prosty skrypt, który generuje nam te wpisy. Używam czcionki DejaVu ponieważ jest "otwarta" i zawiera znaki Unicode.
<pre>#!/bin/bash
FOP="/home/tools/fop/"
INCLUD="${FOP}build/fop.jar:${FOP}lib/avalon-framework.jar:${FOP}lib/commons-logging.jar:${FOP}lib/commons-io.jar:${FOP}lib/xmlgraphics-commons.jar"
for font in `find /home/tools/fonts -name "*.ttf"`;do
NAME=${font%%.*}
java -cp "${INCLUD}" org.apache.fop.fonts.apps.TTFReader "${font}" "${NAME}.xml"
done
for FONT in `find /home/tools/fonts -name "*.ttf" | sort`;do
NAME=${FONT%%.*}
FILE=`basename ${FONT}`
NAME2=${FILE%%.*}
echo "<font metrics-url=\"${NAME}.xml\" kerning=\"yes\" embed-url=\"${FONT}\">"
STYLE="normal"
WEIGHT="normal"
if echo ${NAME2} | grep -qi oblique;then
NAME2=`echo ${NAME2} | sed -re 's/\-?oblique//i'`
STYLE="oblique"
fi
if echo ${NAME2} | grep -qi italic;then
NAME2=`echo ${NAME2} | sed -re 's/\-?italic//i'`
STYLE="italic"
fi
if echo ${NAME2} | grep -qi bold;then
NAME2=`echo ${NAME2} | sed -re 's/\-?bold//i'`
WEIGHT="bold"
fi
echo " <font-triplet name=\"${NAME2}\" style=\"${STYLE}\" weight=\"${WEIGHT}\"/>"
echo "</font>"
done</pre>Zawartość katalogu <code>/home/tools/fonts</code> przed uruchomieniem skryptu:<pre>DejaVuSans-Bold.ttf
DejaVuSans-BoldOblique.ttf
DejaVuSans-ExtraLight.ttf
DejaVuSans-Oblique.ttf
DejaVuSans.ttf
DejaVuSansCondensed-Bold.ttf
DejaVuSansCondensed-BoldOblique.ttf
DejaVuSansCondensed-Oblique.ttf
DejaVuSansCondensed.ttf
DejaVuSansMono-Bold.ttf
DejaVuSansMono-BoldOblique.ttf
DejaVuSansMono-Oblique.ttf
DejaVuSansMono.ttf
DejaVuSerif-Bold.ttf
DejaVuSerif-BoldItalic.ttf
DejaVuSerif-Italic.ttf
DejaVuSerif.ttf
DejaVuSerifCondensed-Bold.ttf
DejaVuSerifCondensed-BoldItalic.ttf
DejaVuSerifCondensed-Italic.ttf
DejaVuSerifCondensed.ttf
</pre>Poniżej rezultat uruchomienia skryptu:
<pre><font metrics-url="/home/tools/fonts/DejaVuSans-Bold.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSans-Bold.ttf">
<font-triplet name="DejaVuSans" style="normal" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSans-BoldOblique.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSans-BoldOblique.ttf">
<font-triplet name="DejaVuSans" style="oblique" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSans-ExtraLight.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSans-ExtraLight.ttf">
<font-triplet name="DejaVuSans-ExtraLight" style="normal" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSans-Oblique.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSans-Oblique.ttf">
<font-triplet name="DejaVuSans" style="oblique" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSans.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSans.ttf">
<font-triplet name="DejaVuSans" style="normal" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansCondensed-Bold.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansCondensed-Bold.ttf">
<font-triplet name="DejaVuSansCondensed" style="normal" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansCondensed-BoldOblique.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansCondensed-BoldOblique.ttf">
<font-triplet name="DejaVuSansCondensed" style="oblique" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansCondensed-Oblique.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansCondensed-Oblique.ttf">
<font-triplet name="DejaVuSansCondensed" style="oblique" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansCondensed.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansCondensed.ttf">
<font-triplet name="DejaVuSansCondensed" style="normal" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansMono-Bold.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansMono-Bold.ttf">
<font-triplet name="DejaVuSansMono" style="normal" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansMono-BoldOblique.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansMono-BoldOblique.ttf">
<font-triplet name="DejaVuSansMono" style="oblique" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansMono-Oblique.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansMono-Oblique.ttf">
<font-triplet name="DejaVuSansMono" style="oblique" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSansMono.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSansMono.ttf">
<font-triplet name="DejaVuSansMono" style="normal" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerif-Bold.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerif-Bold.ttf">
<font-triplet name="DejaVuSerif" style="normal" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerif-BoldItalic.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerif-BoldItalic.ttf">
<font-triplet name="DejaVuSerif" style="italic" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerif-Italic.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerif-Italic.ttf">
<font-triplet name="DejaVuSerif" style="italic" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerif.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerif.ttf">
<font-triplet name="DejaVuSerif" style="normal" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerifCondensed-Bold.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerifCondensed-Bold.ttf">
<font-triplet name="DejaVuSerifCondensed" style="normal" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerifCondensed-BoldItalic.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerifCondensed-BoldItalic.ttf">
<font-triplet name="DejaVuSerifCondensed" style="italic" weight="bold"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerifCondensed-Italic.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerifCondensed-Italic.ttf">
<font-triplet name="DejaVuSerifCondensed" style="italic" weight="normal"/>
</font>
<font metrics-url="/home/tools/fonts/DejaVuSerifCondensed.xml" kerning="yes" embed-url="/home/tools/fonts/DejaVuSerifCondensed.ttf">
<font-triplet name="DejaVuSerifCondensed" style="normal" weight="normal"/>
</font>
</pre>Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-12341228644685227372011-04-06T19:17:00.005+02:002011-04-20T17:49:16.798+02:00Apache FOP na Apache Tomcat cz.4Nie odpuściłem tego servleta... Po pewnych walkach (przypominam, że to moje pierwsze programowanie w Javie), udało się skompilować <code>fop.war</code>.
Dokonane zmiany wyglądają tak:<pre>--- FopServlet.java.org 2010-07-12 21:34:45.000000000 +0200
+++ FopServlet.java 2011-04-06 19:00:01.639060332 +0200
@@ -44,6 +44,10 @@ import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
+import org.xml.sax.SAXException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
/**
* Example servlet to generate a PDF from a servlet.
* <br/>
@@ -77,6 +81,8 @@ public class FopServlet extends HttpServ
/** Name of the parameter used for the XSLT file */
protected static final String XSLT_REQUEST_PARAM = "xslt";
+ private final Log log = LogFactory.getLog(FopServlet.class);
+
/** The TransformerFactory used to create Transformer instances */
protected TransformerFactory transFactory = null;
/** The FopFactory used to create Fop instances */
@@ -94,6 +100,13 @@ public class FopServlet extends HttpServ
//Configure FopFactory as desired
this.fopFactory = FopFactory.newInstance();
this.fopFactory.setURIResolver(this.uriResolver);
+ try {
+ fopFactory.setUserConfig(new File("userconf.xml"));
+ } catch (IOException e) {
+ log.error("No such file or directory", e);
+ } catch (SAXException e) {
+ throw new ServletException(e);
+ }
configureFopFactory();
}
</pre>
Plik konfiguracyjny <code>userconf.xml</code> wrzucamy po prostu do katalogu z Tomcat'em. Jeśli brak jest pliku, generowany jest log, jeśli są błędy w strukturze xml, zgłaszany jest wyjątek.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com1tag:blogger.com,1999:blog-5883011934720163442.post-14780215520734611122011-04-06T10:26:00.020+02:002011-08-10T13:52:37.310+02:00Apache FOP na Apache Tomcat cz.3Ta ścieżka została, odrzucona. Dlaczego? Nie wiem jak podpiąć plik konfiguracyjny. Edycja a później kompilacja nowego servleta nie wchodzi w grę. A potrzebuję własnego pliku konfiguracyjnego aby wrzucić fonty z polskimi znakami. Bez tego ani rusz.
Walki skończyły się na tym, że zrobiłem najprostszego wrappera w PHP, generuję plik <code>.fo</code>, zapisuję w tempie, wywołuję bezpośrednio skrypt <code>fop</code> ze ścieżką do zmodyfikowanego pliku konfiguracyjnego i wypluwam do przeglądarki zawartość wygenerowanego pliku PDF.
Wrapper wygląda następująco:<pre><?php
$fo_tmp = tempnam("/tmp", "fop_fo_");
$pdf_tmp = tempnam("/tmp", "fop_pdf_");
$fo = '<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="first"
page-height="29.7cm"
page-width="21cm"
margin-top="1cm"
margin-bottom="2cm"
margin-left="1cm"
margin-right="1cm">
<fo:region-body margin-top=".5cm"/>
<fo:region-before extent="0cm"/>
<fo:region-after extent="0cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="first">
<fo:flow flow-name="xsl-region-body">
<fo:block">Hello World!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>';
file_put_contents($fo_tmp,$fo);
system("/home/tools/fop/fop -c /home/tools/fop/userconf.xml $fo_tmp $pdf_tmp");
$lastmodified = gmdate('D, d M Y H:i:s \G\M\T',time());
header("Content-Type: application/pdf");
header("Last-Modified: $lastmodified");
$pdf = @file_get_contents($pdf_tmp);
header("Content-Lenght: ".strlen($pdf));
header("Content-Length: ".strlen($pdf));
echo $pdf;
@unlink($fo_tmp);
@unlink($pdf_tmp);
exit;
?></pre>Należy pamiętać o odpowiedniej modyfikacji ścieżek.
Po delikatnych modyfikacjach, możemy dostosować ten wrapper do konwersji plików xml+xslt.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0tag:blogger.com,1999:blog-5883011934720163442.post-59454871559653636132011-03-31T22:44:00.006+02:002011-04-20T17:46:36.620+02:00Apache FOP na Apache Tomcat cz.2Jak człowiek sam nie pokombinuje, to sobie może szukać w necie i oczywistych rzeczy nie zobaczy... Wystarczyło ściągnąć źródła FOPa, przekompilować wszystko <code>ant</code>, przekopiować <code>fop.war</code> do katalogu <code>webapps/</code> i już.
W Slackware, wystarczyło ściagnąć i odpalić Tomcat'a, wcześniej kopiując skompilowany pod Debianem <code>fop.war</code> do katalogu <code>webapps/</code> i... gotowe.Anonymoushttp://www.blogger.com/profile/13938051484250459581noreply@blogger.com0