• 1
  • 2
2010-04-19, 22:28
  #1
Medlem
AquaRegias avatar
Flummig rubrik kanske.. men det är såhär att jag håller på med en IRC-bot, och jag vill att den ska kunna utföra allt man säger åt den att göra. Vad jag har förstått så finns det två saker man kan använda, eval och exec.

Eval tar t.ex. strängen "3+6*2" och returnerar då 15. Försöker man använda t.ex. "print 3+6*2" eller en import eller liknande så kraschar botten.

Exec tar också en sträng (bland annat) som parameter, men den returnerar ingenting, den utför bara det som står i strängen.

Så jag vill på något sätt att botten ska skicka tillbaka resultatet utav det som hände, så om uppgiften var "print 5+5" så ska den returnera 10, var uppgiften "5+5" ska den inte returnera någonting alls osv.

Någon som vet vad jag är ute efter?
Citera
2010-04-20, 09:33
  #2
Medlem
SSHs avatar
Citat:
Ursprungligen postat av AquaRegia
Flummig rubrik kanske.. men det är såhär att jag håller på med en IRC-bot, och jag vill att den ska kunna utföra allt man säger åt den att göra. Vad jag har förstått så finns det två saker man kan använda, eval och exec.

Eval tar t.ex. strängen "3+6*2" och returnerar då 15. Försöker man använda t.ex. "print 3+6*2" eller en import eller liknande så kraschar botten.

Exec tar också en sträng (bland annat) som parameter, men den returnerar ingenting, den utför bara det som står i strängen.

Så jag vill på något sätt att botten ska skicka tillbaka resultatet utav det som hände, så om uppgiften var "print 5+5" så ska den returnera 10, var uppgiften "5+5" ska den inte returnera någonting alls osv.

Någon som vet vad jag är ute efter?

Jag vill först och främst avråda dig från att använda eval och exec, säkerhetsriskerna är alldeles för stora. Bäst vore om du enbart tillät vissa kommandon att köras och att du skrev speciell kod för att parsa och köra dessa. Vill du ändå fortsätta råder jag dig att köra programmet med en användare med få rättigheter.

Om du vill kunna använda ett statement som print är det exec du vill ha. eval kan enbart utvärdera uttryck. Vet inte om det är särskilt snyggt, men man kan få tag i det som skrivs till stdout genom att ändra värde på sys.stdout:
Kod:
import sys
import StringIO

output 
StringIO.StringIO()
sys.stdout output
exec 
"print 1+1"
sys.stdout sys.__stdout__
print output.getvalue() 
__________________
Senast redigerad av SSH 2010-04-20 kl. 09:40.
Citera
2010-04-20, 15:51
  #3
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av SSH
Jag vill först och främst avråda dig från att använda eval och exec, säkerhetsriskerna är alldeles för stora. Bäst vore om du enbart tillät vissa kommandon att köras och att du skrev speciell kod för att parsa och köra dessa. Vill du ändå fortsätta råder jag dig att köra programmet med en användare med få rättigheter.

Om du vill kunna använda ett statement som print är det exec du vill ha. eval kan enbart utvärdera uttryck. Vet inte om det är särskilt snyggt, men man kan få tag i det som skrivs till stdout genom att ändra värde på sys.stdout:
Kod:
import sys
import StringIO

output 
StringIO.StringIO()
sys.stdout output
exec 
"print 1+1"
sys.stdout sys.__stdout__
print output.getvalue() 

Tack för ditt svar.

Först och främst vill jag säga att säkerheten inte är några problem, jag har gjort så att botten bara lyssnar på mig just nu.

Får inte din kod att funka riktigt, låter jag output vara en fil istället så fungerar det alldeles utmärkt. Men med StringIO så förblir den bara tom. Kanske skulle tillägga att jag kör Python 2.6.5 ifall det är det som gör att det spökar.
Citera
2010-04-20, 16:21
  #4
Medlem
SSHs avatar
Citat:
Ursprungligen postat av AquaRegia
Får inte din kod att funka riktigt, låter jag output vara en fil istället så fungerar det alldeles utmärkt. Men med StringIO så förblir den bara tom. Kanske skulle tillägga att jag kör Python 2.6.5 ifall det är det som gör att det spökar.

Konstigt. Har testat det på två datorer med Python 2.6.5 och det fungerade båda gångerna. Är du säker på att det är StringIO som är problemet? Ett annat potentiellt fel kan vara att stdout inte återställs ordentligt och att det är därför inget skrivs ut. Prova att använda StringIO, men skriv resultatet till en fil istället för stdout:
Kod:
import sys
import StringIO

output 
StringIO.StringIO()
sys.stdout output
exec 
"print 1 + 1"
outfile file("fil"'w')
outfile.write(output.getvalue()) 
Citera
2010-04-20, 16:25
  #5
Medlem
Citat:
Ursprungligen postat av AquaRegia
Tack för ditt svar.

Först och främst vill jag säga att säkerheten inte är några problem, jag har gjort så att botten bara lyssnar på mig just nu.

Får inte din kod att funka riktigt, låter jag output vara en fil istället så fungerar det alldeles utmärkt. Men med StringIO så förblir den bara tom. Kanske skulle tillägga att jag kör Python 2.6.5 ifall det är det som gör att det spökar.

Vad är de som inte fungerar?
Går bra att köra exemplet hos mig.

Du kan även peka om stdout till din egen klass, tror den bara behöver ha metoden write
Citera
2010-04-20, 17:07
  #6
Medlem
AquaRegias avatar
Heh, löste "mysteriet". Efter att man har kört en print så att den har hamnat i output så kan man ju inte köra print output för att kolla värdet, eftersom att alla prints skrivs till output. Så:

Kod:
import sys
import StringIO

output = StringIO.StringIO()
sys.stdout = output
exec "print 1 + 1"

print output.getvalue()

outfile = file("fil.txt", 'w')
outfile.write(output.getvalue())

skriver inte ut någonting på skärmen, utan "2\n2" i textfilen.
Citera
2010-04-20, 18:13
  #7
Medlem
Citat:
Ursprungligen postat av AquaRegia
Heh, löste "mysteriet". Efter att man har kört en print så att den har hamnat i output så kan man ju inte köra print output för att kolla värdet, eftersom att alla prints skrivs till output. Så:

Kod:
import sys
import StringIO

output = StringIO.StringIO()
sys.stdout = output
exec "print 1 + 1"

print output.getvalue()

outfile = file("fil.txt", 'w')
outfile.write(output.getvalue())

skriver inte ut någonting på skärmen, utan "2\n2" i textfilen.

därav raden sys.stdout = sys.__stdout__
Citera
2010-04-20, 18:19
  #8
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av balboah
därav raden sys.stdout = sys.__stdout__

Mjo, jag misstänkte det, men det ville inte fungera för mig. Men jag löste det genom att spara sys.stdout innan jag ändrar den.
Citera
2010-04-22, 18:59
  #9
Medlem
AquaRegias avatar
Egentligen ett nytt problem, men jag sitter fortfarande med samma projekt så jag ställer frågan här.

Hur ser ett rått meddelande ut i IRC? Jag menar med efterföljande \r\n och allt sånt där. Jag försöker få den att skriva ut saker i konsolen så som det ser ut i IRC, dvs från ungefär:

:AquaRegia!@adress.någonting.com PRIVMSG #kanal : meddelande

till:

<AquaRegia> meddelande

Och det fungerar egentligen problemfritt förutom att det blir en extra radbrytning mellan varje rad. Någon som vågar gissa varför?
Citera
2010-04-22, 19:06
  #10
Medlem
metapods avatar
Citat:
Ursprungligen postat av AquaRegia
Egentligen ett nytt problem, men jag sitter fortfarande med samma projekt så jag ställer frågan här.

Hur ser ett rått meddelande ut i IRC? Jag menar med efterföljande \r\n och allt sånt där. Jag försöker få den att skriva ut saker i konsolen så som det ser ut i IRC, dvs från ungefär:

:AquaRegia!@adress.någonting.com PRIVMSG #kanal : meddelande

till:

<AquaRegia> meddelande

Och det fungerar egentligen problemfritt förutom att det blir en extra radbrytning mellan varje rad. Någon som vågar gissa varför?

Att du får en dubbelradbrytning är troligtvis för att det meddelande du parse:ar ut från den råa IRC-datan innehåller en radbrytning (vilket är specificerat utav protokollet) - men att du sedan skriver ut en extra.
Citera
2010-04-22, 19:13
  #11
Medlem
AquaRegias avatar
Citat:
Ursprungligen postat av metapod
Att du får en dubbelradbrytning är troligtvis för att det meddelande du parse:ar ut från den råa IRC-datan innehåller en radbrytning (vilket är specificerat utav protokollet) - men att du sedan skriver ut en extra.

Det är därför jag vill veta hur en rå sträng ser ut, jag splittar indatat med "\r\n" vilket "borde" skapa en lista med strängar utan radbrytningar.
Citera
2010-04-22, 19:23
  #12
Medlem
metapods avatar
Citat:
Ursprungligen postat av AquaRegia
Det är därför jag vill veta hur en rå sträng ser ut, jag splittar indatat med "\r\n" vilket "borde" skapa en lista med strängar utan radbrytningar.

IRC-protokollet separerar de olika commands som skickas från servern med en radbrytbning. Således borde denna radbrytning, som du säger, försvinna vid eventuell split om du gör på rätt sätt.

Det du dock måste ha i åtanke är att vissa IRC-servers skickar ut endast "\n" istället för "\r\n" - vilket kan ligga bakom det du beskrivit tidigare..
Citera
  • 1
  • 2

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in