[SQlite3/PHP] Table checken voor IP adress

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Opzet:

Via een form kunnen website bezoekers zich toevoegen aan een sqlite database. Om spam te voorkomen wil ik het aantal insert entries per ip adress (ja ik weet ze kunnen spoofen) limiteren tot 1. Dit is de eerste keer dat ik werk met sqlite en php, wat werkt is dat gebruikers zich kunnen toevoegen aan de database maar ik kan niet limiteren op 1 entry per IP adress, tenminste mijn opgezette 'code' werkt niet.

Relevante code:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
$bnetname = $_POST['bnetname'];
$ip = $_SERVER['REMOTE_ADDR']; 

try
  {
    
    //open the database
    $db = new PDO('sqlite:bnetnames.sqlite');

    //create the database
    $db->exec("CREATE TABLE participants (Id INTEGER PRIMARY KEY, bnetname TEXT, ip INTEGER)");     
    
    // check if an IP adress already is in the table, if it is not then execute the prepared INSERT statement 
    $checkip = $db->query("SELECT * FROM participants WHERE ip LIKE '$ip'");

    //prepare INSERT statement
    $stmt= $db->prepare("INSERT INTO participants(bnetname, ip) VALUES (:bnetname, :ip)");
    
        //bind statement variables directly to input values
    $stmt->bindParam(':bnetname', $bnetname, SQLITE3_TEXT);
    $stmt->bindParam(':ip', $ip, SQLITE3_TEXT);
    
    //Execute INSERT statement if a name has been filled in and IP is not already in db
    if ((!empty($bnetname))&&($name="validate")&&(empty($checkip)))
        {
    $stmt->execute();
    }
?>

 


Ik zie zo snel niet wat ik fout doe en heb ook nog de volgende bedenkingen:
> Is mijn sql/php syntax correct voor de IP query, vooral het aanspreken van php variable $ip binnen een SELECT statement.
> Kan ik wel empty() gebruiken voor het resultaat van een query (wat een array is toch?)/

Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 09-09 12:00

TheNephilim

Wtfuzzle

Maar wat is de foutmelding die je krijgt?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
TheNephilim schreef op donderdag 14 juni 2012 @ 16:44:
Maar wat is de foutmelding die je krijgt?
Ik krijg gewoon een blanco pagina, is er soort van debug mode dan? heb zelf geen aparte code voor exceptions erin gezet.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Nu online

MueR

Admin Tweakers Discord

is niet lief

Hint: display_errors en error_reporting

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • curvemod
  • Registratie: Maart 2009
  • Laatst online: 06-09 20:43
MueR schreef op donderdag 14 juni 2012 @ 16:56:
Hint: display_errors en error_reporting
Jep, het is alleen nog makkelijker om in je errorlogs te kijken

Linux: tail -f -n 20 /var/log/apache2/error.log

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Ja, want iedereen gebruikt ook linux, apache2 en dezelfde instellingen voor apache... :Z

Gewoon lekker display_errors aan en error_reporting deftig instellen dus.

Acties:
  • 0 Henk 'm!

  • curvemod
  • Registratie: Maart 2009
  • Laatst online: 06-09 20:43
Cartman! schreef op donderdag 14 juni 2012 @ 17:09:
Ja, want iedereen gebruikt ook linux, apache2 en dezelfde instellingen voor apache... :Z

Gewoon lekker display_errors aan en error_reporting deftig instellen dus.
Volgens mij is het een stuk beter om dit uit je errorlogs te halen dan het naar je scherm te schrijven, zeker met wat langere stacktraces. En ja, de meeste mensen gebruiken inderdaad apache 2, je kan anders ook gewoon een locate doen of op windows in Xampp kijken waar je errorlog stat.

Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 10:57
Ik zou nog eens goed kijken naar het datatype van je IP. Je definieert de tabel als een INTEGER maar stopt daar hard strings in.

Ik zie ook niet hoe '1.2.3.4' zou passen dan, maar SQLite heeft wel gekkere dingen :P

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
jhuiting schreef op donderdag 14 juni 2012 @ 17:16:
Volgens mij is het een stuk beter om dit uit je errorlogs te halen dan het naar je scherm te schrijven, zeker met wat langere stacktraces.
Tijdens development vind ik ze op het scherm veel handiger, dan hoef ik niet te switchen van venster.
En ja, de meeste mensen gebruiken inderdaad apache 2, je kan anders ook gewoon een locate doen of op windows in Xampp kijken waar je errorlog stat.
Ze gebruiken misschien wel apache2, maar niet specifiek op linux of op die locatie die jij zegt. Je brengt het alsof dat command voor iedereen gaat werken maar dat is simpelweg niet zo.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Resolved, bedankt voor de reply's!

Heb mijn php.ini aangepast:
code:
1
2
display_errors = on  
error_reporting = E_all & ~E_notice

Zowel /var/log/apache2/error.log en de weergegeven error in de browser gaven aan dat ik een ")'' miste vandaar de witte pagina.

Nu deed de site nog niks, even elk onderdeel van de IP filter in volgorde uit/aangezet.
PHP:
1
 $checkip = $db->query("SELECT * FROM participants WHERE ip LIKE '$ip'");

Was in orde en returned de juiste waardes, ondanks van wat Darkmage opmerkte dat ik inderdaad IP als integer had gedefinieerd (maar later wel weer gebind als text).

Maar deze voorwaarde pakt php niet:
PHP:
1
2
if ((!empty($bnetname))&&($name="validate")&&(empty($checkip)))
{ etc....}


Nu heb ik maar even een lelijke oplossing erin gezet dat wel werkt
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
....
$checkip = $db->query("SELECT * FROM participants WHERE ip LIKE '$ip'");
    $alreadyinDB=0;
    foreach($checkip as $row)
    {
      $alreadyinDB=1;
    }

.....

//Execute INSERT statement if a name has been filled in
    if ((!empty($bnetname))&&($name="validate")&&($alreadyinDB==0)){
    $stmt->execute();
    }
    elseif ((!empty($bnetname))&&($name="validate")&&($alreadyinDB==1)){
    print "Only 1 entry per IP is allowed";
    }

Acties:
  • 0 Henk 'm!

  • HyperioN
  • Registratie: April 2003
  • Laatst online: 24-05 15:42
Verwijderd schreef op donderdag 14 juni 2012 @ 17:51:

Maar deze voorwaarde pakt php niet:

Nu heb ik maar even een lelijke oplossing erin gezet dat wel werkt
Dus omdat je er niet 1,2,3 uitkomt ga je een lelijke workaround (dus geen oplossing) verzinnen?

Hint:
http://php.net/manual/en/language.operators.comparison.php

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:30
Tja, empty() werkt alleen op primitive types, niet op PDOStatement objecten; die zijn nooit empty. Je kunt wel $checkip->rowcount() gebruiken, bijvoorbeeld.

Je gebruikt daar verder een paar keer de assignment operator (=) waar je een comparison operator (==) bedoelt.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Soultaker schreef op donderdag 14 juni 2012 @ 18:01:
Tja, empty() werkt alleen op primitive types, niet op PDOStatement objecten; die zijn nooit empty. Je kunt wel $checkip->rowcount() gebruiken, bijvoorbeeld.

Je gebruikt daar verder een paar keer de assignment operator (=) waar je een comparison operator (==) bedoelt.
Ah thanks zoiets vermoedde ik al, maar omdat SQLite in de CLI niks output bij dezelfde query dacht ik met empty wel te kunnen werken.

//todo fix comparison operators en change to rowcount() :D

Acties:
  • 0 Henk 'm!

  • spleethoven
  • Registratie: Oktober 2010
  • Laatst online: 24-01-2024
code:
1
if ((!empty($bnetname))&&($name="validate")&&($alreadyinDB==0)){


er staat nog een foutje in, je hebt een haakje teveel.

Acties:
  • 0 Henk 'm!

  • Fusioxan
  • Registratie: November 2009
  • Laatst online: 10:03
Nee toch?
code:
1
2
3
4
5
6
7
if (
 (!empty($bnetname))
 &&
 ($name="validate")
 &&
 ($alreadyinDB==0)
)


OT:
Volgens mij is het probleem al opgelost, maar het type van je IP-veld in de database zou ook een varchar(39) kunnen zijn. Varchar(15) is nu nog wel genoeg, maar ik weet niet hoe future-proof je script moet zijn? IPv6 eist namelijk maximaal 39 (8×4+7) karakters, terwijl IPv4 nog genoeg heeft aan 15 (4×3+3).

Acties:
  • 0 Henk 'm!

  • HyperioN
  • Registratie: April 2003
  • Laatst online: 24-05 15:42
Fusioxan schreef op vrijdag 15 juni 2012 @ 13:17:
Nee toch?
code:
1
2
3
4
5
6
7
if (
 (!empty($bnetname))
 &&
 ($name="validate")
 &&
 ($alreadyinDB==0)
)
Inderdaad.. wel, zoals al opgemerkt een = te weinig.
OT:
Volgens mij is het probleem al opgelost, maar het type van je IP-veld in de database zou ook een varchar(39) kunnen zijn. Varchar(15) is nu nog wel genoeg, maar ik weet niet hoe future-proof je script moet zijn? IPv6 eist namelijk maximaal 39 (8×4+7) karakters, terwijl IPv4 nog genoeg heeft aan 15 (4×3+3).
Nog beter, onder het motto van efficientie:
http://dev.mysql.com/doc/...s.html#function_inet-aton
Maak een unsigned int veld voor je ip-adres en doe:
SQL:
1
INSERT INTO table SET ip = INET_ATON('173.194.67.94')


Opzoeken of ophalen doe je dan zo:
SQL:
1
SELECT INET_NTOA(ip) FROM table

En dan komt er gewoon weer een leesbaar IP-adres uit.
Is ook veel sneller dan.

Momenteel nog geen IPv6-support, maar vanaf MySQL 6.0 wel (http://forge.mysql.com/worklog/task.php?id=798). Dan ondersteunen de INET-functies IPv6 en dan komt er zelfs een datatype voor:
the proposed new data types CIDR and INET
allow IPv6 format as described in
WL#2037 "Add CIDR and INET data types"

[ Voor 9% gewijzigd door HyperioN op 15-06-2012 14:01 ]


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
Mag ik vragen wat er mis is met een unieke index op het ip veld? En dan de exception van de insert mooi opvangen?
Pagina: 1