trunk 20080912
[gitenigma.git] / src / upgrade.cpp
blob42284f639b1f4b2fd4a8a5388725e94c1a5d7dec
1 #include "upgrade.h"
2 #include <unistd.h>
3 #include <xmltree.h>
4 #include <enigma.h>
5 #include <lib/gui/ebutton.h>
6 #include <lib/gui/statusbar.h>
7 #include <lib/gui/emessage.h>
8 #include <lib/gui/eprogress.h>
9 #include <lib/gui/eskin.h>
10 #include <lib/dvb/decoder.h>
11 #include <lib/dvb/edvb.h>
12 #include <lib/system/info.h>
13 #include <lib/gdi/font.h>
14 #include <lib/gdi/epng.h>
15 #include <lib/gdi/gfbdc.h>
16 #include <lib/gdi/fb.h>
17 #include <libmd5sum.h>
19 #include <sys/mman.h>
21 #include <linux/version.h>
22 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
23 #include <linux/compiler.h>
24 #endif
25 #include <mtd/mtd-user.h>
26 #include <sys/ioctl.h>
27 #include <sys/mount.h>
29 #define TMP_IMAGE "/tmp/root.cramfs"
30 #define TMP_IMAGE_ALT "/tmp/cdk.cramfs"
31 #define TMP_CHANGELOG "/tmp/changelog"
33 class ProgressWindow: public eWindow
35 public:
36 eProgress progress;
37 ProgressWindow( const char * );
40 ProgressWindow::ProgressWindow( const char *wtext )
41 :eWindow(0), progress(this)
43 move(ePoint(100,250));
44 cresize(eSize(470,50));
45 setText(wtext);
46 progress.move(ePoint(10,10));
47 progress.resize(eSize(450,30));
50 static eString getVersionInfo(const char *info)
52 FILE *f=fopen("/.version", "rt");
53 if (!f)
54 return "";
55 eString result;
56 while (1)
58 char buffer[128];
59 if (!fgets(buffer, 128, f))
60 break;
61 if (strlen(buffer))
62 buffer[strlen(buffer)-1]=0;
63 if ((!strncmp(buffer, info, strlen(info)) && (buffer[strlen(info)]=='=')))
65 int i = strlen(info)+1;
66 result = eString(buffer).mid(i, strlen(buffer)-i);
67 break;
70 fclose(f);
71 return result;
74 eListBoxEntryImage::eListBoxEntryImage
75 (eListBox<eListBoxEntryImage> *listbox, eString name, eString target, eString url, eString version, eString creator, const unsigned char md5[16])
76 : eListBoxEntryText((eListBox<eListBoxEntryText> *)listbox, name),
77 name(name), target(target), url(url), version(version), creator(creator)
79 if (md5)
80 memcpy(this->md5, md5, 16);
81 else
82 memset(this->md5, 0, 16);
85 eHTTPDownload::eHTTPDownload(eHTTPConnection *c, const char *filename): eHTTPDataSource(c), filename(filename)
87 if (c->remote_header.count("Content-Length"))
88 total=atoi(c->remote_header["Content-Length"].c_str());
89 else
90 total=-1;
91 received=0;
92 fd=::creat(filename, 0777);
93 progress(received, total);
96 eHTTPDownload::~eHTTPDownload()
98 if (fd >= 0)
99 ::close(fd);
100 if ((total != -1) && (total != received))
101 ::unlink(filename.c_str());
104 void eHTTPDownload::haveData(void *data, int len)
106 if (len)
108 if (fd >= 0)
109 ::write(fd, data, len);
111 received+=len;
112 progress(received, total);
115 eHTTPDownloadXML::eHTTPDownloadXML(eHTTPConnection *c, XMLTreeParser &parser): eHTTPDataSource(c), parser(parser)
117 error=0;
118 errorstring="";
121 void eHTTPDownloadXML::haveData(void *data, int len)
123 if ((!error) && (!parser.Parse((char*)data, len, !data)))
125 errorstring.sprintf("XML parse error: %s at line %d",
126 parser.ErrorString(parser.GetErrorCode()),
127 parser.GetCurrentLineNumber());
128 error=1;
132 eUpgrade::eUpgrade(bool manual)
133 :http(0), changelog(0)
135 status = new eStatusBar(this);
136 status->setFlags(eStatusBar::flagOwnerDraw);
137 status->loadDeco();
138 status->setName("status");
140 images=new eListBox<eListBoxEntryImage>(this);
141 images->setName("images");
142 CONNECT(images->selected, eUpgrade::imageSelected);
143 CONNECT(images->selchanged, eUpgrade::imageSelchanged);
145 imagehelp=new eLabel(this);
146 imagehelp->setName("imagehelp");
147 imagehelp->setText(_("Please select the software version to upgrade to:"));
149 progress=new eProgress(this);
150 progress->setName("progress");
151 progress->hide();
153 progresstext=new eLabel(this);
154 progresstext->setName("progresstext");
155 progresstext->hide();
157 changes=new eLabel(this, RS_WRAP);
158 changes->setName("changes");
160 abort=new eButton(this);
161 abort->setName("abort");
162 CONNECT(abort->selected, eUpgrade::abortDownload);
163 abort->hide();
165 if (eSkin::getActive()->build(this, "eUpgrade"))
166 eFatal("skin load of \"eUpgrade\" failed");
168 catalog=0;
169 changelog=0;
171 mIDStr=eSystemInfo::getInstance()->getmidStr();
173 eString caturl=getVersionInfo("catalog");
175 if (caturl.length() && !manual )
176 loadCatalog(caturl.c_str());
178 ourversion=getVersionInfo("version");
180 struct stat s;
181 if (!stat(TMP_IMAGE_ALT, &s))
182 rename(TMP_IMAGE_ALT, TMP_IMAGE);
183 if (!stat(TMP_IMAGE, &s))
184 new eListBoxEntryImage(images, _("manual upload"), "", "", "", "", 0);
186 setHelpID(94);
189 void eUpgrade::loadCatalog(const char *url)
191 current_url=url;
192 int error;
193 if (catalog)
194 delete catalog;
195 catalog=new XMLTreeParser("ISO-8859-1");
196 http=eHTTPConnection::doRequest(url, eApp, &error);
197 if (!http)
199 catalogTransferDone(error);
200 } else
202 setStatus(_("downloading catalog..."));
203 CONNECT(http->transferDone, eUpgrade::catalogTransferDone);
204 CONNECT(http->createDataSource, eUpgrade::createCatalogDataSink);
205 http->local_header["User-Agent"]="enigma-upgrade/1.0.0";
206 http->start();
210 void eUpgrade::loadChangelog(const char *url)
212 current_url=url;
213 int error;
214 if (changelog)
215 delete changelog;
216 changelog=eHTTPConnection::doRequest(url, eApp, &error);
217 if (!changelog)
219 changelogTransferDone(error);
220 } else
222 setStatus(_("downloading changelog..."));
223 CONNECT(changelog->transferDone, eUpgrade::changelogTransferDone);
224 CONNECT(changelog->createDataSource, eUpgrade::createChangelogDataSink);
225 changelog->local_header["User-Agent"]="enigma-upgrade/1.0.0";
226 changelog->start();
230 void eUpgrade::loadImage(const char *url)
232 images->hide();
233 imagehelp->hide();
234 current_url=url;
235 int error;
236 if (http)
237 delete http;
238 progress->show();
239 progresstext->show();
240 abort->show();
241 http=eHTTPConnection::doRequest(url, eApp, &error);
242 if (!http)
244 imageTransferDone(error);
245 } else
247 setStatus(_("downloading image..."));
248 CONNECT(http->transferDone, eUpgrade::imageTransferDone);
249 CONNECT(http->createDataSource, eUpgrade::createImageDataSink);
250 http->local_header["User-Agent"]="enigma-upgrade/1.0.0";
251 http->start();
255 void eUpgrade::catalogTransferDone(int err)
257 if ((!err) && http && (http->code == 200) && datacatalog && !datacatalog->error)
259 XMLTreeNode *root=catalog->RootNode();
260 eString mytarget=mIDStr;
261 images->beginAtomic();
262 for (XMLTreeNode *r=root->GetChild(); r; r=r->GetNext())
264 if (!strcmp(r->GetType(), "image"))
266 const char *name=r->GetAttributeValue("name");
267 const char *url=r->GetAttributeValue("url");
268 const char *version=r->GetAttributeValue("version");
269 const char *target=r->GetAttributeValue("target");
270 const char *creator=r->GetAttributeValue("creator");
271 const char *amd5=r->GetAttributeValue("md5");
272 unsigned char md5[16];
273 if (!creator)
274 creator=_("unknown");
275 if (!amd5)
276 continue;
277 for (int i=0; i<32; i+=2)
279 char x[3];
280 x[0]=amd5[i];
281 if (!x[0])
282 break;
283 x[1]=amd5[i+1];
284 if (!x[1])
285 break;
286 int v=0;
287 if (sscanf(x, "%02x", &v) != 1)
288 break;
289 md5[i/2]=v;
291 if (!(name && url && version && target))
292 continue;
293 if (!strstr(target, mytarget.c_str()))
294 continue;
295 new eListBoxEntryImage(images, name, target, url, version, creator, md5);
296 } else if (!strcmp(r->GetType(), "changelog"))
298 const char *changelog=r->GetAttributeValue("url");
299 if (changelog)
300 loadChangelog(changelog);
303 setFocus(images);
304 images->endAtomic();
305 setStatus(_("Please select version to upgrade or LAME! to abort"));
306 if (images->getCurrent())
307 imageSelchanged(images->getCurrent());
308 } else
310 if (err || http->code !=200)
311 setError(err);
312 else if (datacatalog)
314 eDebug("data error.");
315 // setStatus(datacatalog->errorstring);
316 setStatus("XML parse error.");
319 if (catalog)
320 delete catalog;
321 http=0;
324 void flashImage(int checkmd5);
326 void eUpgrade::imageTransferDone(int err)
328 progress->hide();
329 progresstext->hide();
330 abort->hide();
331 if (err || !http || http->code != 200)
332 setError(err);
333 else
334 flashImage(1);
335 http=0;
336 images->show();
337 imagehelp->show();
340 void eUpgrade::changelogTransferDone(int err)
342 if (err || !changelog || changelog->code != 200)
344 setError(err);
345 } else
347 FILE *f=fopen(TMP_CHANGELOG, "rt");
348 if (f)
350 char temp[1024];
351 while (fgets(temp, 1024, f))
353 if (*temp)
354 temp[strlen(temp)-1]=0; // remove trailng \n
355 eString str(temp);
356 changelogEntry entry;
358 entry.date=str.left(12);
359 entry.priority=str[13]-'0';
360 entry.text=str.mid(15);
361 unsigned int in=entry.text.find(' ');
362 entry.machines="*";
363 if (in != eString::npos)
365 entry.machines=entry.text.left(in);
366 entry.text=entry.text.mid(in+1);
368 changelogentries.push_back(entry);
370 fclose(f);
372 displayChangelog(ourversion.mid(4), selectedversion.mid(4), mIDStr);
374 changelog=0;
377 void eUpgrade::imageSelected(eListBoxEntryImage *img)
379 if (img)
381 if (img->url.length())
383 memcpy(expected_md5, img->md5, 16);
384 setStatus(img->url);
385 loadImage(img->url.c_str());
386 } else
387 flashImage(0);
388 } else
389 close(0); // aborted
392 void eUpgrade::imageSelchanged(eListBoxEntryImage *img)
394 selectedversion=img->version;
395 displayChangelog(ourversion.mid(4), selectedversion.mid(4), mIDStr);
398 void eUpgrade::setStatus(const eString &string)
400 status->setText(string);
403 void eUpgrade::setError(int err)
405 eString errmsg;
406 switch (err)
408 case 0:
409 if (http && http->code != 200)
410 errmsg="error: server replied " + eString().setNum(http->code) + " " + http->code_descr;
411 break;
412 case -2:
413 errmsg="Can't resolve hostname!";
414 break;
415 case -3:
416 errmsg="Can't connect! (check network settings)";
417 break;
418 default:
419 errmsg.sprintf("unknown error %d", err);
421 setStatus(errmsg);
422 if (errmsg.length())
424 if (current_url.length())
425 errmsg+="\n(URL: " + current_url + ")";
426 eMessageBox box(errmsg, _("Error!"), eMessageBox::btOK|eMessageBox::iconError);
427 box.show();
428 box.exec();
429 box.hide();
433 eHTTPDataSource *eUpgrade::createCatalogDataSink(eHTTPConnection *conn)
435 return datacatalog=new eHTTPDownloadXML(conn, *catalog);
438 eHTTPDataSource *eUpgrade::createImageDataSink(eHTTPConnection *conn)
440 image=new eHTTPDownload(conn, TMP_IMAGE);
441 lasttime=0;
442 CONNECT(image->progress, eUpgrade::downloadProgress);
443 return image;
446 eHTTPDataSource *eUpgrade::createChangelogDataSink(eHTTPConnection *conn)
448 changelogdownload=new eHTTPDownload(conn, TMP_CHANGELOG);
449 lasttime=0;
450 CONNECT(changelogdownload->progress, eUpgrade::downloadProgress);
451 return changelogdownload;
454 void eUpgrade::downloadProgress(int received, int total)
456 if ((time(0) == lasttime) && (received != total))
457 return;
458 lasttime=time(0);
459 if (total > 0)
461 eString pt;
462 int perc=received*100/total;
463 pt.sprintf("%d/%d kb (%d%%)", received/1024, total/1024, perc);
464 progress->setPerc(perc);
465 progresstext->setText(pt);
466 } else
468 eString pt;
469 pt.sprintf("%d kb", received/1024);
470 progress->setPerc(0);
471 progresstext->setText(pt);
475 void eUpgrade::abortDownload()
477 if (http)
479 delete http;
480 http=0;
482 setStatus(_("Download aborted."));
483 progress->hide();
484 progresstext->hide();
485 abort->hide();
486 images->show();
487 imagehelp->show();
490 bool erase(char mtd[30], const char *titleText);
492 #ifdef USE_EXTERNAL_FLASHTOOL
493 static int flashext=1;
494 #else
495 static int flashext=0;
496 #endif
497 // when you will use the external flashtool you must set this here to 1
499 void eUpgrade::flashImage(int checkmd5)
501 setStatus(_("checking consistency of file..."));
502 unsigned char md5[16];
503 if (checkmd5 && md5_file (TMP_IMAGE, 1, (unsigned char*) &md5))
505 setStatus(_("write error while downloading..."));
506 eMessageBox mb(
507 _("write error while downloading..."),
508 _("Error!"),
509 eMessageBox::btOK|eMessageBox::iconError);
510 hide();
511 mb.show();
512 mb.exec();
513 mb.hide();
514 show();
515 } else
517 if (checkmd5 && memcmp(md5, expected_md5, 16))
519 setStatus(_("Data error. The checksum didn't match."));
520 eMessageBox mb(
521 _("Data error. The checksum didn't match."),
522 _("Error!"),
523 eMessageBox::btOK|eMessageBox::iconError);
524 hide();
525 mb.show();
526 mb.exec();
527 mb.hide();
528 show();
529 } else
531 setStatus(_("Checksum OK. Ready to upgrade."));
532 eMessageBox mb(
533 _("Are you sure you want to upgrade to this new version?"),
534 _("Ready to upgrade"),
535 eMessageBox::btYes|eMessageBox::btNo|eMessageBox::iconQuestion);
536 int mtdsize;
537 hide();
538 mb.show();
539 int res=mb.exec();
540 mb.hide();
541 if (res == eMessageBox::btYes)
543 ::sync();
544 Decoder::Flush();
545 char mtd[20];
546 int mID = atoi(mIDStr.c_str());
547 switch (mID)
549 case 1: // d-box2
550 case 2:
551 case 3:
552 strcpy(mtd,"/dev/mtd/2");
553 mtdsize=0x6e0000;
554 break;
555 case 5: // dm7000
556 case 6: // dm56xx
557 case 7: // dm500
558 case 8: // tr272S
559 strcpy(mtd,"/dev/mtd/0");
560 mtdsize=0x600000;
561 break;
562 default:
563 strcpy(mtd,"/dev/null");
564 mtdsize=0;
566 int fd1=0,fd2=0;
568 if( (fd1 = open( TMP_IMAGE, O_RDONLY )) < 0 )
570 eMessageBox box(_("Can't read flashimage.img!"), _("Flash"), eMessageBox::iconInfo|eMessageBox::btOK );
571 box.show();
572 box.exec();
573 box.hide();
574 close(0);
575 return;
578 int filesize = lseek( fd1, 0, SEEK_END);
579 lseek( fd1, 0, SEEK_SET);
581 if(filesize==0)
583 eMessageBox box(_("flashimage.img has filesize of 0byte!"), _("Flash"), eMessageBox::iconInfo|eMessageBox::btOK );
584 box.show();
585 box.exec();
586 box.hide();
587 return;
590 if ( flashext )
592 ::close(fd1);
593 __u8 data[720*576];
594 gPixmap pixmap;
595 pixmap.x=720;
596 pixmap.y=576;
597 pixmap.bpp=8;
598 pixmap.bypp=1;
599 pixmap.stride=720;
600 pixmap.data=data;
601 pixmap.clut.colors=256;
602 pixmap.clut.data=gFBDC::getInstance()->getPixmap().clut.data;
603 gPixmapDC outputDC(&pixmap);
604 eWidget virtualRoot;
605 virtualRoot.move(ePoint(0, 0));
606 virtualRoot.resize(eSize(720, 576));
607 virtualRoot.setTarget(&outputDC);
608 virtualRoot.makeRoot();
609 virtualRoot.setBackgroundColor(gColor(0));
610 virtualRoot.show();
612 eMessageBox mb(
613 _("Please wait... do NOT switch off the receiver!"),
614 _("upgrade in progress"), eMessageBox::iconInfo);
615 mb.show();
617 ProgressWindow wnd(_("Erasing Flash..."));
618 wnd.show();
619 while(gRC::getInstance().mustDraw())
620 usleep(1000);
621 // if ( !savePNG("/tmp/update1.png", &pixmap) )
622 // eDebug("saved update pic 1");
623 int fd = open("/tmp/update1.raw", O_CREAT|O_WRONLY|O_TRUNC);
624 if ( fd >= 0 )
626 ePoint pos = wnd.progress.getAbsolutePosition();
627 int x = 2+pos.x(); // borderwidth+xpos..
628 int y = 2+pos.y(); // borderwidth+ypos..
629 int fillColor = eSkin::getActive()->queryScheme("eProgress.left").color;
630 int width = wnd.progress.getSize().width()-4;
631 int height = wnd.progress.getSize().height()-4;
632 write(fd, &x, sizeof(x));
633 write(fd, &y, sizeof(y));
634 write(fd, &width, sizeof(width));
635 write(fd, &height, sizeof(height));
636 write(fd, &fillColor, sizeof(fillColor));
637 write(fd, pixmap.data, 720*576*pixmap.bpp/8);
638 ::close(fd);
642 ProgressWindow wnd(_("Writing Software to Flash..."));
643 wnd.show();
644 while(gRC::getInstance().mustDraw())
645 usleep(1000);
646 // if ( !savePNG("/tmp/update2.png", &pixmap) )
647 // eDebug("saved update pic 2");
648 int fd = open("/tmp/update2.raw", O_CREAT|O_WRONLY|O_TRUNC);
649 if ( fd >= 0 )
651 ePoint pos = wnd.progress.getAbsolutePosition();
652 int x = 2+pos.x(); // borderwidth+xpos..
653 int y = 2+pos.y(); // borderwidth+ypos..
654 int fillColor = eSkin::getActive()->queryScheme("eProgress.left").color;
655 int width = wnd.progress.getSize().width()-4;
656 int height = wnd.progress.getSize().height()-4;
657 write(fd, &x, sizeof(x));
658 write(fd, &y, sizeof(y));
659 write(fd, &width, sizeof(width));
660 write(fd, &height, sizeof(height));
661 write(fd, &fillColor, sizeof(fillColor));
662 write(fd, pixmap.data, 720*576*pixmap.bpp/8);
663 ::close(fd);
667 pixmap.clut.data=0;
668 int fd = open("/tmp/mtd.txt", O_WRONLY|O_CREAT|O_TRUNC);
669 if ( fd >= 0 )
671 write(fd, mtd, strlen(mtd));
672 ::close(fd);
674 struct fb_cmap* cmap = fbClass::getInstance()->CMAP();
675 fd = open("/tmp/cmap", O_WRONLY|O_CREAT|O_TRUNC);
676 if ( fd >= 0 )
678 write(fd, &cmap->start, sizeof(cmap->start));
679 write(fd, &cmap->len, sizeof(cmap->len));
680 write(fd, cmap->red, cmap->len*sizeof(__u16));
681 write(fd, cmap->green, cmap->len*sizeof(__u16));
682 write(fd, cmap->blue, cmap->len*sizeof(__u16));
683 write(fd, cmap->transp, cmap->len*sizeof(__u16));
684 ::close(fd);
686 eZap::getInstance()->getDesktop(eZap::desktopFB)->makeRoot();
687 fbClass::getInstance()->lock();
689 else
691 eMessageBox mb(
692 _("Please wait... do NOT switch off the receiver!"),
693 _("upgrade in progress"), eMessageBox::iconInfo);
694 mb.show();
696 // without this nice we have not enough priority for
697 // file operations... then the update ist very slow on the
698 // dreambox
699 nice(-10);
700 eEPGCache::getInstance()->messages.send(eEPGCache::Message(eEPGCache::Message::pause));
702 system("cp /sbin/rebootSE /tmp/reboot");
704 if(!erase(mtd,_("Erasing Flash...")))
706 mb.hide();
707 eMessageBox box(_("Erase error!"), _("Flash"), eMessageBox::iconInfo|eMessageBox::btOK );
708 box.show();
709 box.exec();
710 box.hide();
711 close(0);
712 return;
715 if( (fd2 = open(mtd, O_RDWR )) < 0 )
717 mb.hide();
718 eMessageBox box(_("Can't open mtd!"), _("Flash"), eMessageBox::iconInfo|eMessageBox::btOK );
719 box.show();
720 box.exec();
721 box.hide();
722 close(0);
723 return;
726 mtd_info_t meminfo;
727 if( ioctl( fd2, MEMGETINFO, &meminfo ) != 0 )
729 close(0);
730 return;
733 ProgressWindow wnd(_("Writing Software to Flash..."));
734 wnd.show();
736 char buf[meminfo.erasesize];
738 int fsize=filesize;
740 eDebug("flashing now...");
742 int rbytes=0;
743 while( ( rbytes = read( fd1, buf, sizeof(buf) ) ) )
745 fsize -= write( fd2, buf, rbytes );
746 wnd.progress.setPerc( ((filesize-fsize)*100)/filesize );
748 ::close(fd1);
749 ::close(fd2);
751 nice(0);
753 mb.hide();
754 wnd.hide();
756 eMessageBox mbend(
757 _("upgrade successful!\nrestarting..."),
758 _("upgrade ok"),
759 eMessageBox::btOK|eMessageBox::iconInfo);
760 mbend.show();
761 mbend.exec();
762 mbend.hide();
764 eZap::getInstance()->quit(3);
765 // system("/sbin/reboot");
766 // system("/bin/reboot");
767 // exit(0);
768 } else
769 close(0);
774 bool erase(char mtd[30], const char *titleText)
776 int fd;
777 mtd_info_t meminfo;
778 erase_info_t erase;
780 if( (fd = open( mtd, O_RDWR )) < 0 )
781 return false;
783 if( ioctl( fd, MEMGETINFO, &meminfo ) != 0 )
784 return false;
786 ProgressWindow wnd(titleText);
787 wnd.show();
789 erase.length = meminfo.erasesize;
790 for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize )
792 eDebugNoNewLine("\rErasing %u Kibyte @ %x -- %2u %% complete",
793 meminfo.erasesize/1024, erase.start,
794 erase.start*100/meminfo.size );
796 wnd.progress.setPerc( erase.start*100/meminfo.size );
798 if(ioctl( fd, MEMERASE, &erase) != 0)
800 ::close(fd);
801 wnd.hide();
802 return false;
805 wnd.hide();
807 ::close(fd);
809 return true;
812 void eUpgrade::displayChangelog(eString oldversion, eString newversion, eString mid)
814 eString changetext;
815 if (newversion.empty())
817 changetext="";
818 } else if (oldversion == newversion)
820 changetext=_("This is the currently installed release.");
821 } else if (oldversion > newversion)
823 changetext=_("This is an older release.");
824 } else if (changelogentries.empty())
826 changetext=_("No changelog data available.");
827 } else
829 // build list of changetext
831 std::multimap<int,eString> pchanges;
832 for (std::list<changelogEntry>::const_iterator i(changelogentries.begin());
833 i != changelogentries.end(); ++i)
835 // check if change is new for this version
836 if ((i->date > oldversion) && (i->date <= newversion) && ((i->machines=="*") || (i->machines.find(mid) != eString::npos)))
837 pchanges.insert(std::pair<int,eString>(i->priority, i->text));
839 if (pchanges.empty())
840 changetext=_("No new features were added in this release.");
841 else
843 changetext=_("The following new features were added in this release:\n");
844 for (std::map<int,eString>::const_iterator i(pchanges.begin());
845 i != pchanges.end(); ++i)
846 changetext+=" * " + i->second + "\n";
849 changes->setText(changetext);
852 eUpgrade::~eUpgrade()
854 if (http)
855 delete http;
856 if (changelog)
857 delete changelog;