priloha a word dokument

Programovacie jazyky, rady, poradňa...
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

priloha a word dokument

Príspevok od používateľa Snacker »

Zdravim,
Mam jeden zvlastny problem, ktory riesim uz zopar dni ale zatial sa mi ho nepodarilo rozlusknut.
Ide o to, ze robim mailove rozhranie. Princip je taky, ze ak je sprava nova ulozime ju do databazy, prilohy ulozime na server a potom spravu z mail servera vymazem. A tak precitane spravy taham iba z MySQL.

Tu je kod (tenpracuje fajn)

Kód: Vybrať všetko

<?php
// ak je prava , nova cize nepreciana  tak ...
if(isset($_GET['id'])){
$id = $_GET['id'];
$mbox = imap_open ("{localhost:995/pop3/ssl/novalidate-cert}", $nick."@priklad.com", $password);
$hlavicka = imap_header($mbox, $id);

$from = $hlavicka->from[0];
$adresa = $from->mailbox."@".$from->host;
$odosielatel = $from->personal;
$predmet = $hlavicka->Subject;
$datum = $hlavicka->Date;
$sprava = imap_body($mbox, $id);

// komu -> mne
$komu = $nick."priklad.com";
// Ak sprava obsahuje prilohu tak oddel text od prilohy
$st = imap_fetchstructure($mbox, $id);
if (!empty($st->parts)) {
    for ($i = 0, $j = count($st->parts); $i < $j; $i++) {
        $part = $st->parts[$i];
        if ($part->subtype == 'PLAIN') {
             $body = imap_fetchbody($mbox, $id, $i+1);
             $priloha = 1;
        }
     }
} else {
    $body = imap_body($mbox, $id);
    $priloha = 0;
}

// Teraz INSERT-neme celu spravu, ktoru sme si vytiahli so mail servera do databazy MySQL -> tab. mails
$server = "localhost";
$username = "******";
$password = "******";
$databaza = "email";

@mysql_pconnect($server, $username, $password) or die("Nemozem nadviazat spojenie s databazou!");
@mysql_select_db($databaza) or die("Nemozem nadviazat spojenie s databazou!");

$vlozenie = mysql_query("INSERT INTO `email`.`mails` (`id` ,`nick` ,`od` ,`komu` ,`predmet` ,`cas` ,`sprava` ,`stav` )VALUES (NULL , '$nick', '$adresa', '$komu', '$predmet', '$datum', '$body', '1')");

// Vyvorime priecinok pre danu spravu. Identifikator podla ID z tab. mails
$results = mysql_query("SELECT id FROM `email`.`mails` WHERE cas='$datum'");
$id_priecinok = mysql_result($results, 0, "id");

mkdir("attachment/$nick/$id_priecinok", 0333);
chmod("attachment/$nick/$id_priecinok", 0333);

// Ak sprava obsahuje prilohu vyberieme ju(ich) a ulozime na server
if($priloha == 1){
$structure=imap_fetchstructure($mbox, $id); // druhy parameter je poradove cislo spravy
$encoding=$structure->encoding;
$parts=$structure->parts;
$num_parts=sizeof($parts);

for($i=1;$i<=$num_parts;$i++){ // cislo prilohy 1 lebo 2 alebo 3 ...
$info=get_info($parts[$i]);

$name=$info['name']; // nazov suboru s koncovkou
$mime=$info['mime']; // Typ suboru
$transfer=$info['transfer']; // Kodovanie
$size=$info['size']; // Velkost

// ulozenie prilohy na server
$file = imap_fetchbody($mbox, $id, ($i+1));  //druhy parameter je cislo spravy, tretie cislo je 1-text 2-1.prihloha 3-2.priloha ...
$tFile = "attachment/$nick/$id_priecinok/$name";
$tFileHandle = fopen($tFile, "w");

fwrite($tFileHandle, imap_base64($file));
fclose ($tFileHandle);
?>
Tu si treba vsimnut funkciu get_info(), ktora mi zabezpecuje informacie o prilohe (nazov suboru s koncovkou,typ suboru, kodovanie a velkost) a na zaklade tychto udajov ukladam prilohu na server.

Funkcia get_info() vyzera pomerne jednoducho :

Kód: Vybrať všetko

function get_info($part) 
{ 
  $name = "[unknown]"; 
  // popis časti 
  if($part->ifdescription == true) $description = $part->description; 
  // meno  // chyba je v mene suboru
  
      echo "PART->TYPE:".$part->type;

  
  for($i=0;$i<count($part->parameters);$i++) 
  { 
    $parameter = $part->parameters[$i]; 
    if((($parameter->attribute=="name") || ($parameter->attribute=="NAME")) && ($parameter->value!="")) 
    { 
      $name = $parameter->value; 
      break; 
    } 
  } 
  // typ 
  if(isset($part->type)): 
    switch($part->type) 
    { 
      case 0: 
      $type = "text"; 
      break; 
      case 1: 
      $type = "multipart"; 
      break; 
      case 2: 
      $type = "message"; 
      break; 
      case 3: 
      $type = "application"; 
      break; 
      case 4: 
      $type = "audio"; 
      break; 
      case 5: 
      $type = "image"; 
      break; 
      case 6: 
      $type = "video"; 
      break; 
      case 7: 
      $type = "other"; 
        break; 
      default: 
      $type = "unknown"; 
      break; 
    } 
  endif; 
  // mime 
  $mime = $type."/".$part->subtype; 
  // kódovanie 
  if(isset($part->encoding)): 
    switch($part->encoding) 
    { 
      case 0: 
      $encoding = "7BIT"; 
      break; 
      case 1: 
      $encoding = "8BIT"; 
      break; 
      case 2: 
      $encoding = "BINARY"; 
      break; 
      case 3: 
      $encoding = "BASE64"; 
      break; 
      case 4: 
      $encoding = "QUOTED-PRINTABLE"; 
      break; 
      case 5: 
      $encoding = "OTHER"; 
      break; 
      default: 
      $encoding = "none"; 
      break; 
    } 
  else: 
    $encoding = "7BIT"; 
  endif; 
  // veľkosť 
  $size = $part->bytes; 
  if($size>1000) $size = ceil($size/1000); 
  else $size = 1; 
  // spolu 
  $info = array 
  ( 
  "name" => $name, 
  "mime" => $mime, 
  "transfer" =>$encoding, 
  "size" =>$size, 
  ); 
  return $info; 
}
A tu nastava spominany problem. Konkretne v casti

Kód: Vybrať všetko

for($i=0;$i<count($part->parameters);$i++) 
  { 
    $parameter = $part->parameters[$i]; 
    if((($parameter->attribute=="name") || ($parameter->attribute=="NAME")) && ($parameter->value!="")) 
    { 
      $name = $parameter->value; 
      break; 
    } 
Zip, JPG,TXT je ok. Ale ak mam prilohu typu Word(2007)alebo Powerpoint nastava fatal error:
Fatal error: Cannot use object of type stdClass as array in...
Zvlastne je, ze pri ostatnych typoch suborov je vsetko ok.

Ak by mi niekto vedel poradit bol by somvelmi vdacny.

Dakujem

// este doplnim ze skript je estedost nedoladeny preotoze sa prioritne zameriavam na tuto chybu.(napr. kodovanie je prednastavene na base64-ku no vskutocnosti by tam mala byt estepodmienka, inak ulozeny subor bude poruseny)
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

skús dať pred tým cyklom var_dump($part) a čo ti to vyhodí. Vypadé že v ňom nie je pole aké očakávaš
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

Kód: Vybrať všetko

PART->TYPE:3object(stdClass)#17 (13) { ["type"]=> int(3) ["encoding"]=> int(3) ["ifsubtype"]=> int(1) ["subtype"]=> string(58) "VND.OPENXMLFORMATS-OFFICEDOCUMENT.WORDPROCESSINGML.DOCUMEN" ["ifdescription"]=> int(0) ["ifid"]=> int(0) ["bytes"]=> int(35866) ["ifdisposition"]=> int(1) ["disposition"]=> string(10) "ATTACHMENT" ["ifdparameters"]=> int(1) ["dparameters"]=> array(1) { [0]=> object(stdClass)#18 (2) { ["attribute"]=> string(8) "FILENAME" ["value"]=> string(8) "PHP.docx" } } ["ifparameters"]=> int(0) ["parameters"]=> object(stdClass)#19 (0) { } }
PHP.docx je ten wordacky dokument
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

v $part->parameters máš objekt, a nie pole. Neviem čo tam word dáva a či ti to treba. Buď si to teda ošetríš v podmienke (napríklad is_array() ) alebo sa pozri cez var_dump čo je v tom objekte a uvidíme ďalej
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

Aky zapis potrebujem ak chcem pozriet ten objekt? Skusal som var_dump($part->parameters) ale vypisuje mi len object(stdClass)#19 (0) { } ...
Potreboval by som asi ten objekt prekonvertovat na pole ci nie?
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

skús to nejak takto:

Kód: Vybrať všetko

if($part->ifparameters){
for($i=0;$i<count($part->parameters);$i++)
  {
    $parameter = $part->parameters[$i];
    if((strtolower($parameter->attribute)=="name") && ($parameter->value!=""))
    {
      $name = $parameter->value;
      break;
    }
} else if($part->ifdparameters){
for($i=0;$i<count($part->dparameters);$i++)
  {
    $parameter = $part->dparameters[$i];
    if((strtolower($parameter->attribute)=="name") && ($parameter->value!=""))
    {
      $name = $parameter->value;
      break;
    }
}
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

Myslel si to dobre ale neboloto funkcne. Nepridelovalo mi k tomu meno ale aspon to nevypisovalo chybu. Potom som skusil dat var_dump() na zip subor a tiez sa tam nachadzal parameter dparameters a tak som skusil taku vec, ze budem nazov suboru urcovat podla neho.
A tak som skusil:

Kód: Vybrať všetko

for($i=0;$i<count($part->dparameters);$i++) 
  { 
    $parameter = $part->dparameters[$i]; 
    $name = $parameter->value; 
}
a vsetko bezi ako ma. Subory sa mi este neotvoria dobre lebo tam este nemam dobre kodovanie(aspon dufam :) ) ale inak to ide. Dnas to dam este do dobreho kodovania, keby nieco napisem ale kazdopadne ti patri VELKA VDAKA bez teba by som nemal sancu :wink:
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

nemá name, ale filename :) to som prehliadol keďže som to iba kopíroval a prepínal medzi tabmi :) Nevermind, keď to ide tak nechaj tak ako to máš (ale pri iných to možno bude robiť šarapatu). Ak to ale chceš mať tak ako to máš (a teda si v tom cykle prepisuješ stále $name) tak nemusíš vôbec robiť cyklus ale zober posledný parameter. Efekt bude rovnaký nakoľko si teraz tú premennú $name v každom cykle prepíšeš
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

Tieto vecicky som praveze doplnil ale nebolo to funkcne ale potom som to spravil takto a moc som sa s tym uz nezaoberal.

//autoeditácia príspevku ( 05 Jul 2009, 19:01 )
//
Ano az teraz ma napadlo ze staci posledny parameter vziat. Skusal som excel, word, zip, pdf, powerpoint, txt. To by hadam aj mohlo stacit :lol:

//autoeditácia príspevku ( 10 Jul 2009, 11:59 )
Prisiel som na jednu chybu.
Ak poslem prilohu s diakritikou tak sa mi nazov suboru uplne zblbne.
var_dump() mi ukazuje:

Kód: Vybrať všetko

object(stdClass)#5 (13) { ["type"]=> int(3) ["encoding"]=> int(3) ["ifsubtype"]=> int(1) ["subtype"]=> string(58) "VND.OPENXMLFORMATS-OFFICEDOCUMENT.WORDPROCESSINGML.DOCUMEN" ["ifdescription"]=> int(0) ["ifid"]=> int(0) ["bytes"]=> int(40128) ["ifdisposition"]=> int(1) ["disposition"]=> string(10) "ATTACHMENT" ["ifdparameters"]=> int(1) ["dparameters"]=> array(1) { [0]=> object(stdClass)#6 (2) { ["attribute"]=> string(8) "FILENAME" ["value"]=> string(41) " =?iso-8859-2?Q?VIRTU=C1LNY_SERVER.docx?=" } } ["ifparameters"]=> int(0) ["parameters"]=> object(stdClass)#7 (0) { } } 
Teda FILENAME (nazve subor) ?iso-8859-2?Q?VIRTU=C1LNY_SERVER.docx?=
spravne by malo byt VIRTUÁLNY SERVER.docx

iso-8859-2 mi tam da asi, ze v akom je to kodovani ale ako spravim aby som podla toho kodovania aj spravne pomenoval subor?

Dakujem
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

To som uz skusal ale nic to nespravi pretoze ja mam v
$name = " ?iso-8859-2?Q?VIRTU=C1LNY_SERVER.docx?=";

a ked dam napr.
$name = iconv('iso-8859-2', 'Windows-1250', $name);

tak mi to vrati to iste


Uz to mam:

Kód: Vybrať všetko

<?php
$text = "=?iso-8859-2?Q?VIRTU=C1LNY_SERVER.docx?=";

$elements = imap_mime_header_decode($text);
for ($i=0; $i<count($elements); $i++) 
    echo $elements[$i]->text;
?>
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

to Q znamená "Q"uoted-Printable, ešte môže byť B ako "B"ase64-encoded. Ty to potrebuješ najprv dekodovať, a potom to môžeš prekonvertovať na utf8. K tomu iconv čo som ti poslal si pozri ešte imap_mime_header_decode()
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

diki za pomoc
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

teraz kukám že iconv ti ani nebud treba, ono sa to postará o správny prevod. Takže tá funkcia môže vypadať

Kód: Vybrať všetko

function decode($input) {
 	$array = imap_mime_header_decode($input);
	return $array[0]->text;
}
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

ano ano, aj ja som si to vsimol :) Este som sa ta chcel tak pomimo spytat ake by bolo najvhodnejsie kodovanie pre mna. Robim jeden taky vacsi projekt (blogy, mail, chat, download suborov atd.) a web bude miltijazycny. Mam tam zatial windows 1250 a nerobi problem. Mal by som to dat do UTF-8 ?
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

radšej použiť charset s väčším množstvom znakov ako mať potom málo. Ja som vo svojom cms používal utf8 (aj keď sa to nedá presne povedať, lebo každá stránka mohla mať vlastné kodovanie ktoré sa dalo zmeniť cez cp)
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

ok, tak som aj myslel, urcite je lepsie mat charset vacsim poctom znakov, aspon v mojom pripade... ja moc redakcne systemy nemusim, rad si robim vsetko pekne sam :wink:
Este raz diki moc za cenne rady
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Príspevok od používateľa audiotrack »

spojením "vo svojom cms" som mal na mysli cms ktoré som naprogramoval ja
Snacker
Medium Star
Medium Star
Používateľov profilový obrázok
Príspevky: 362
Registrovaný: 08 jún 2009, 22:42
Kontaktovať používateľa:

Príspevok od používateľa Snacker »

:lol: sorac, som to len tak prebehol ocami :)
Napísať odpoveď