Google rezultāti

Nupat pamanīju, ka Googles rezultātu lapa ir nedaudz mainījusies. Ja agrāk, meklējot Google kaut ko un atrodot arī rezultātus iekš naivist.net, parādījās links

<a href="http://naivist.net" ...

tad tagad links ir

<a href="http://www.google.lv/url?sa=U&start=1&q=http://naivist.net&e=10342"...

Un tas savukārt nozīmē to, ka Google grib nevis piedāvāt Tev rezultātus, bet arī uzzināt, kuru no rezultātiem Tu esi izvēlējies kā interesantus. Protams, tas nozīmē, ka uz šo datu pamata viņi attīstīs savas tehnoloģijas. Bet no otras puses, tas, protams, nozīmē, ka Google zina par Tevi vēl vairāk.

UPD: šķiet, ka šīs izmaiņas tomēr nav gluži globālas un ir saistītas ar to, ka esmu kaut ko nospiedis apmeklējot google personalizēto versiju un turklāt vienlaicīgi biju ielogojies arī Gmail.

Par RSS

Šodien pamanīju pavisam jauku lietu un nodomāju – kāpēc gan tā nedarīt?

Tātad, špikojam no Microsoft Software Developer Network mājas lapas RSS plūsmām. Katrā XML failā, kas tiek piedāvāts kā plūsma (piemēram, šis), ir iekļauta XSL direktīva, kas viņu gadījumā izskatās šādi:

<?xml-stylesheet type='text/xsl' href='rsspretty.xsl' version='1.0'?>

Savukārt pats rsspretty.xsl fails ņem un transformē RSS plūsmas datus lietotājam baudāmā izskatā: pieliek dokumenta sākumu, kurā pastāsta, kas tā ir par plūsmu un kāds ir tās saturs, pēc tam izdrukā plūsmā esošos rakstus secīgi, parādot description, autoru, publicēšanas datumu.

Rezultātā, ja RSS plūsmas fails tiek atvērts ar vizuālu tīmekļa pārlūku, kas spēj rādīt XSL transformētus XML failus, parādās gandrīz normāla lapa. Ja RSS plūsmas failu atver nevizuāls aģents – tas darīs, kas nu tam jādara.

Modulus

Rakstot par nesmukajiem datumiem, biju izmantojis šādu izteiksmi: $sundayEveningSpan = ((($now["wday"]-1)%7)*24*60*60);. Rezultātā mainīgais $sundayEveningSpan tiek uzstādīts (tam vajadzētu tikt uzstādītam) uz sekunžu skaitu starp šodienas plkst. 00:00 un šīs pirmdienas 00:00. Vārdu sakot, tiek aprēķināts, cik sekundes pagājušas šajā nedēļā.

Kā redzams, izteiksmē parādās operators %, kas atgriež izteiksmes $now["wday"]-1 vērtību pēc moduļa 7. Tas darīts tāpēc, ka PHP funkcijas GetDate() atgrieztajā masīvā wday lauks atgriež “Numeric representation of the day of the week: 0 (for Sunday) through 6 (for Saturday)”. Tātad svētdiena ir 0-tā diena, sestiena ir 6. diena. Tā kā man (un arī daudziem citiem latviešiem) nedēļa sākas ar pirmdienu, no dienas numura bija jāatņem vieninieks pēc moduļa 7, lai iegūtu pareizo piekārtojumu: pirmdienai 0, svētdienai (0-1) mod 7, kas vienāds ar 6 klasiskajā moduļu aritmētikā.

Tomēr izrādījās, ka šādi mana funkcija darbojas nekorekti. Izpētot tuvāk, secināju, ka PHP valodai arī ir savas īpatnības – modulis no negatīva skaitļa ir negatīvs. Tas arī oficiāli ir dokumentēts modulus operatora aprakstā. Tādēļ -1 % 7==-6, nevis 6, kā bija sagaidāms.

Lai novērstu šīs PHP īpatnības sekas, aizstājam -1 ar +6 (kas ir kongruenti pēc moduļa 7) un turpmāk nedēļas sākumu aprēķinām šādi: $sundayEveningSpan = ((($now["wday"]+6)%7)*24*60*60);.

Kā rāda testi, šāda pat problēma novērojama arī Visual Basic.Net un, ļoti iespējams, arī citās .Net valodās. Kā sacīts MSDN, “The result of x Mod y is the value produced by x – (x \ y) * y”. Tas nozīmē, ka gadījumā, kad pats x ir negatīvs, arī atgrieztais rezultāts būs negatīvs.

Tā, lūk. Atliek vien secināt, ka programmēšanas valodu veidotājiem ir vienalga, vai tiek saglabāta multiplikatīvās grupas pēc moduļa N un gredzena īpašība, kas tik svarīga ir matemātiķiem. Un tas, protams, ir tikai normāli – ja vajadzēs, vienmēr varēsim pieskaitīt 6 tā vietā, lai atņemtu 1.

Nesmukie laiki

Šodien mani kaunināja, ka es nesmuki datumus rakstot. Ka “02.06.2005. 07:21:22” patiesībā cilvēkam neko neizsaka. Cita lieta, ja paziņotu vienkārši “vakar” – tas jau daudz labāk izklausoties. Taisnība jau arī ir – cilvēks nav dators, cilvēkam BIOS-ā nav iešūts kalendārs.

Tāpēc funkcija, kas UNIX timestampam atgriež elementāros vārdiskos aprakstus. Tā sacīt, izkrāso pati, ja gribi citādi:

function TextInfo($spTime){
    $todayMidNight = mktime(0, 0, 0, date("m"), date("d"), date("y"));
    $yesterdayMidNight = $todayMidNight - 24*60*60;


    $nowTime = mktime();        //brīdis, pret kuru rēķinās
    $now = getdate($nowTime); //aprēķina brīža dati sadalīti pa "detaļām"

    //timestamp pagājušās svētdienas beigām
    $sundayEveningSpan = ((($now["wday"]+6)%7)*24*60*60); 

    $then = getdate($spTime); //laiks, pret kuru rēķinās sadalīts pa "detaļām"

    //vai sakrīt ar šodienu
    if ( ($now["mday"]==$then["mday"]) && 
        ($now["mon"]==$then["mon"]) && 
        ($now["year"]==$then["year"])) {
    if ($then["hours"] &lt; 6) return "šonakt"; //noticis šajā naktī
    if ($then["hours"] &lt; 10) return "šorīt"; //noticis rīta pusē
    return "šodien";  //citādi vienkārši informējam, ka šodien 
    }

    //ir noticis vakardien
    if ( ($todayMidNight &gt; $spTime) && ($spTime >= $yesterdayMidNight)) {
    if ( abs( $now["hours"] - $then["hours"] ) &lt; 3) return "vakar ap šo laiku";  //ja stundas līdzīgas pašreizējām
    if ($then["hours"] &lt; 6) return "vakar naktī"; //noticis vakar no rīta agri
    if ($then["hours"] &lt; 10) return "vakar no rīta"; 
    if ($then["hours"] &lt; 12) return "vakar priekšpusdienā"; 
    return "vakar";
    }

    //ir noticis šonedēļ
    if (( $todayMidNight > $spTime) &&  ($todayMidNight- $sundayEveningSpan < $spTime )) {
    return "šonedēļ";
    }

    //ir noticis pagājušajā nedēļā
    if (( $todayMidNight- $sundayEveningSpan > $spTime) && 
        ( $todayMidNight- $sundayEveningSpan - 24*60*60*7 &lt; $spTime )) {
    return "pagājušajā nedēļā";
    }

    //ja senāk par pagājušo nedēļu, vai nav senāk par gadu?
    $tSpan = $nowTime - $spTime;
    if (floor($tspan /(24*60*60*365) )>0) return " pirms vairāk nekā gada";

    //aizmirstam īsos un garos mēnešus
    $tSpanMonths = floor( $tSpan / (24*60*60*30) );     
    if ($tSpanMonths &gt; 0) {
    //starp 1 un 2 mēnešiem
    if ($tSpanMonths == 1) {
        $days = floor(($tSpan-24*60*60*30)/(24*60*60));
        if ( ($days!=1) && ($days!=21) && ($days!=31)) 
        return "pirms mēneša un ".$days." dienām";
                            Else
        return "pirms mēneša un ".$days." dienas";
        }
    return "pirms vairāk nekā ".$tSpanMonths." mēnešiem";
    } else {
    //jāskatās, vai bija tas pats mēnesis, vai iepriekšējais
    if ($then["mon"]==$now["mon"]) return "šajā mēnesī"; else return "pagājušajā mēnesī";
    }
}

Parametros Unix timestamps.

Iexplorer ContextMenu

Attiecībā uz tīmekļa sistēmu drošību ir teiciens, ka 100% droša sistēma būs 0% lietojama. Tātad, jo drošāk, jo neērtāk. Tā kā pēdējā laikā ir populāri dažādi phishing pasākumi, arī .lv internetbankas cenšas panākt arvien augstāku savu pakalpojumu drošību. Līdz ar to ne tik vien tiek izmantoti SSL pieslēgumi, nesaprotami lietotāja vārdi un pieprasītas garas un sarežģītas paroles, bet arī tiek lietotas kodu kartes (tās ir tādas kartiņas ar daudzām burtu/skaitļu virknītēm, katrai virknītei savs numuriņš. Pieslēdzoties e-bankai tiek pieprasīts ievadīt kādu no virknītēm, piemēram septīto pēc kārtas).

Ideja jau skaista, bet lietojamība… katru reizi, kad gribi apskatīties, kā tavā kontā vēl joprojām ir tikai 3 santīmi, tev jāmeklē karte, uz tās jāmeklē kodi, tie “jāpārdrukā” u.t.t.

Šeit pastāstīšu risinājumu, kā papildināt Internet Explorer contextMenu ar savu funkciju, kas atgriež vajadzīgo kodu kartes ierakstu.

“Gudrību” iešujam JavaScript koda gabalā, kurš pārbauda, vai pārlūkprogramma atrodas manas internetbankas lapā un pēc tam no kodu kartes atrod vajadzīgo kodu un to iekopē “starpliktuvē” (clipboard).

< SCRIPT LANGUAGE="JavaScript">
var parentwin = external.menuArguments;
var doc = parentwin.document;
var sel = doc.selection;
var rng = sel.createRange();
var iNum = 0;

//vai esam nokļuvuši e-bankā
if (external.menuArguments.location.host=="mana.e-banka.lv") {

    //ja jā, tad uzstāda kodu kartes vērtības
    var myCodes = new Array("*****", "*****", "*****", "*****", 
                             "*****", "*****", "*****", "*****",
                             "*****", "*****", "*****", "*****", 
                             "*****", "*****", "*****", "*****");
    //kas iezīmēts browser logā?
    if (rng.text!="")
        iNum = rng.text*1;
        //ja iezīmēts skaitlis, mēģina nolasīt kodu
        if (!isNaN(iNum)) 
            window.clipboardData.setData("Text", myCodes[iNum-1]);
        else 
            alert("Nav iezīmēts skaitlis!") 
    }
else {
   alert("Šobrīd Tu neesi bankas lapā!");
}
< /SCRIPT>

Šādu skriptu saglabājam .htm failā uz cietā diska. Piemēram iekš, c:\i\banka.htm Pēc tam veram vaļā RegEdit, un meklējam šādu zaru: HKEYCURRENTUSER\Software\Microsoft\Internet Explorer\MenuExt Iespējams, tur jau priekšā būs kādi ieraksti no Tilde vai kāda cita programmatūras izstrādātāja, kurš savus produktus integrē MSIE. Pievienojam jaunu atslēgu, tās nosaukums būs redzams konteksta dialogā. Piemēram, es pievienoju atslēgu ar nosaukumu “&KoduKarte”. Atslēgas Default vērtību uzstāda uz .htm failu, kurā saglabāts skripts, tas ir manā gadījumā, c:\i\banka.htm Papildus tam, atslēgā pievieno DWORD vērtību Contexts, kurā ierakstām “10”. Tas nozīmē, ka funkcija kontekstu dialogā būs redzama tikai tad, kad ir iezīmēts teksts. Eksportējot no reģistra, atslēga izskatās šādi:

[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\&KoduKarte]
@="c:\\i\\banka.htm"
"Contexts"=dword:00000010

Pēc tam atliek atvērt jaunu InternetExplorer logu un tajā jau būs pieejama jaunā funkcija. Tikai tad, kad būs atvērta internetbankas lapa, tikai tad, kad būs iezīmēts teksts un nospiesta peles labā poga.

Vēlreiz brīdinu, ka šādi darīt nav labi un pavisam noteikti IR SLIKTI, jo šādā veidā Tu samazini Tavas bankas izveidotās drošības sistēmas drošības līmeni. Jo gadījumā, ja kādam citam būs pieeja Tava datora cietajam diskam, viņš(a) varēs nolasīt failu, kur glabājas kodi un tad viņam(ai) atliks TIKAI UZMINĒT TAVU LIETOTĀJA VĀRDU UN PAROLI, lai iekļūtu bankas lapā!

UzKlikšķa

Bieži vien gribas darīt šādi:

<a href="javascript:ShowPic('image1.jpg')">skatīt bildi</a>

Tas ir, lai parādītu bildīti, izsaucam JavaScript funkciju, kurai parametros nododam attēla nosaukumu. Risinājums labi darbosies itin daudziem lietotājiem, tomēr viegli pārliecināties, ka rezultāts nebūs sasniegts, kad pārlūkā atslēgsim JavaScript atbalstu. Turklāt – javascript: lietošana hipersaites href atribūta vērtībā ir nekorekta – šajā atribūtā jānorāda URI shēmai atbilstoša vērtība. javascript: ir pseidoprotokols, līdzīgi kā about: vai chrome:.

Daži problēmu risinātu šādi:

<a href="#" onclick="ShowPic('image1.jpg')">skatīt bildi</a>

Diemžēl šāds risinājums vēl joprojām nepalīdzēs gadījumā, kad pārlūkā atslēgsim JavaScript atbalstu. Mēģināsim lietot <a> birku tam, kam tā domāta – saites norādīšanai. To varam izdarīt šādi

<a href="image1.jpg" onclick="ShowPic('image1.jpg');return false">skatīt bildi</a>

Nu jau izskatās itin labi. Tie pārlūki, kas neatbalsta JavaScript vai arī kam izslēgts javascript, atvērs pašu bildi, bet pārējie izpildīs funkciju ShowPic(), kas droši vien parāda attēlu citā un skaistākā veidā. Papildus pievienotais “return false” nodrošina to, ka pēc funkcijas izpildes notikums “ir ticis uzklikšķināts uz hipersaites” tiek atcelts, tādējādi pārlūks neatvērs adresi, kas aprakstīta href atribūtā.

Tomēr – ak vai, ak vai – šāds dokuments, kam DOCTYPE norādīts XHTML 1.0 Strict negrib "validēties" Tā kā XHTML standarts paredz striktu nodalījumu starp dokumenta saturu (pats XHTML), tā izkārtojumu (CSS stili) un prezentāciju (piekārtotie skripti), tad atribūts onclick vairs nav pieļaujams A elementam.

Tāpēc darām šādi: pašā XHTML dokumentā iekļaujam tikai šādu saiti:

<a href="image1.jpg" class="PictureLink">skatīt bildi</a>

Savukārt dokumentam piekārtotajā skriptu failā piesaistām šim elementam notikumu ķērāju:

//pēc dokumenta pilnas ielādes, izsauc funkciju, kas "salabo" saites
document.body.onload=InitPictureLinks;

//funkcija iziet cauri visām dokumenta hipersaitēm un vajadzīgās no tām "salabo" function InitPictureLinks(){ var oLinks; //šī būs visu hipersaišu kolekcija

//izmanto DOM funkciju, lai nolasītu visas hipersaites oLinks = document.getElementsByTagName("A");

for (var i=0;i<olinks .length;i++){ //apstrādā tikai tos A elementus, kuru klase ir PictureLink if (oLinks[i].className=="PictureLink") addLink(oLinks[i];) } }

//piesaista notikumu ķērāju "onclick". //pēc klikšķa tiek izsaukta funkcija ShowPic, parametros //nododot href atribūtā uzstādīto vērtību un atgriezts false, //lai atceltu klikšķa notikumu function addLink(opLink){ opLink.onclick = function(){ShowPic(opLink.href);return false}; }

FrontPage markup

Īss veids, kā tikt vaļā no FrontPage radītajām sliktajām lietām html kodā, ja “tāpat jau nāksies tam visam iet ar roku cauri”. Darām apmēram tā:

$dati=$_POST["dati"];
$dati=strip_tags($dati, &quot;&lt;a&gt;&lt;b&gt;&lt;i&gt;&lt;p&gt;&lt;br&gt;&quot;);
$dati=preg_replace(&quot;/(class|style|align)=\"[^\"]+\"/i&quot;, &quot;&quot;, $dati);

Tādējādi no formas (vai vienalga kādā veidā) saņemtais mainīgais $dati tiek iztīrīts un tālāk ir cilvēkam lietojams. Līdz ar to tekstā nedrīkst parādīties substringi kā class="kautkas", bet par to jau FrontPage parūpēsies, aizvietojot tos ar attiecīgiem html entities.

Vertikālā centrēšana

Izmantojot CSS, ir grūti centrēt objektu pa vertikāli pret apkārtējo konteinera objektu.
Ja ir zināms objekta augstums, var izmantot sekojošu workaroundu:
Ievietojam papildus vēl vienu elementu, kuru pozicionējam pēc šādas shēmas

position:absolute;
top:50%;
left:50%;
, proti, tā kreisais augšējais stūris atrodas apkārtējā konteinera centrā. Zinot centrējamā objekta augstumu un platumu (piemērā – augstums 80 px, platums:160px), izvēlamies palīgobjekta vertikālo un horizontālo nobīdi:
margin-top:-40px;
margin-left:-80px;
Nobīde ir negatīva, kas nozīmē, ka šobrīd palīgobjekta kreisais augšējais stūris ir nobīdīts no centra tieši par pusi no centrējamā objekta atbilstošajām dimensijām.
Centrēšanas piemērs.

Mazliet par elementāro objektorientāciju

Mazliet par elementāro objektorientāciju PHP (tālāk rakstītais uz PHP 4.x, bet, ļoti iespējams, attieksies arī uz PHP 5.x)
PHP izveidot klasi ir pavisam vienkārši. Rakstām

class TestKlase{}
un ir deklarēta jauna klase TestKlase. Līdz ar to turpmāk PHP kodā var rakstīt
$TesVar = new TestKlase();
un būs zināms pavisam droši, ka $TestVar ir klases TestKlase objekta instance. Klasē var definēt arī iekšējos mainīgos, sauktus par atribūtiem. To dara šādi – tūlīt aiz klases nosaukuma deklarāciajs raksta atsevišķas rindas, kas sākas ar var un turpinās ar atribūta vārdu (un, iespējams, sākumvērtības definīciju). Tas ir,
class TestKlase{
var $TestAtt1;
var $TestAtt2 = ‘1’;}
Līdz ar to, veidojot jaunu klases instanci, atribūts TestAtt2 iegūs vērtību ‘1’,bet TestAtt1 vērtību neiegūs vis. Vērtību inicializatori var būt tikai konstantes, ne dinamiski aprēķinātas vērtības (piemēram, datums). Par klases konstruktoru tiek uzskatīta funkcija, kuras nosaukums sakrīt ar klases vārdu.
class TestKlase{
function TestKlase(){
   $this->TestAtt1=”lalala”;
}
}
Kā redzams, šīs klases konstruktors uzstāda atribūta TestAtt1 vērtību uz string tipa mainīgo “lalala”.
Klases iekšpusē, lai piekļūtu dotās instances atribūtu vērtībām, jālieto mainīgais $this, kas vienmēr norāda uz doto klases instanci (tieši tāpat kā valodā C++).
Klases metodes rakstāmas tieši tāpat kā parastas PHP funkcijas (kas tās pēc būtības arī ir), ieskaitot mainīgo redzamības apgabalu lietojumu, tas ir, lai piekļūtu globāliem mainīgajiem metodē jādeklarē mainīgais kā globāls, piemēram
function TestMethod(){
global $TABULASNOSAUKUMS;
}
. Klases, kas ir objektu kolekcijas, ir viegli veidot, izmantojot array objektu un arraypush() metodi, bet tos pēc tam apstaigāt, izmantojot
foreach ($this->TestVars as $test){
printr($test);
}
Ērta funkcija klases instances apskatīšanai ir printr().