1/*
2 *
3 * kPPP: A pppd front end for the KDE project
4 *
5 * $Id$
6 *
7 * (c) 1998 Mario Weilguni <mweilguni@kde.org>
8 *
9 * Copyright (C) 1997 Bernd Johannes Wuebben
10 * wuebben@math.cornell.edu
11 *
12 * based on EzPPP:
13 * Copyright (C) 1997 Jay Painter
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Library General Public
17 * License as published by the Free Software Foundation; either
18 * version 2 of the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Library General Public License for more details.
24 *
25 * You should have received a copy of the GNU Library General Public
26 * License along with this program; if not, write to the Free
27 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 */
29
30#include <qlabel.h>
31#include <qdir.h>
32#include <qpushbutton.h>
33//Added by qt3to4:
34#include <QVBoxLayout>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <ctype.h>
39#include <unistd.h>
40#include <sys/stat.h>
41
42#include <kdialog.h>
43#include <qregexp.h>
44#include <QTextEdit>
45#include <qlayout.h>
46
47#include <kmessagebox.h>
48#include <kvbox.h>
49
50#include "pppdata.h"
51#include "requester.h"
52#include <klocale.h>
53
54
55int PPPL_MakeLog(QStringList &list) {
56 int pid = -1, newpid;
57 char buffer[1024], *p;
58 const char *pidp;
59 int fd;
60
61 fd = Requester::rq->openSysLog();
62 if(fd < 0) {
63 list.append(i18n("Cannot open any of the following logfiles:"));
64 const char * const * logFile = &kppp_syslog[0];
65 while(*logFile) {
66 list.append(*logFile);
67 logFile++;
68 }
69 return 1;
70 }
71
72 FILE *f = fdopen(fd, "r");
73 while(fgets(buffer, sizeof(buffer), f) != 0) {
74 // pppd line ?
75 p = (char *)strstr(buffer, "pppd[");
76 if(p == 0)
77 continue;
78 pidp = p += strlen("pppd[");
79 while(*p && isdigit(*p))
80 p++;
81 if(*p != ']')
82 continue;
83
84 /* find out pid of pppd */
85 sscanf(pidp, "%d", &newpid);
86 if(newpid != pid) {
87 pid = newpid;
88 list.clear();
89 }
90 if(buffer[strlen(buffer)-1] == '\n')
91 buffer[strlen(buffer)-1] = '\0';
92 list.append(buffer);
93 }
94 fclose(f);
95
96 if(list.isEmpty())
97 return 2;
98
99 /* clear security related info */
100
101 const char *keyword[] = {"name = \"",
102 "user=\"",
103 "password=\"",
104 0};
105
106 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
107 {
108 QByteArray tmp = (*it).toLocal8Bit();
109 for(int j = 0; keyword[j] != 0; j++) {
110 char *p;
111
112 if( (p = (char *)strstr(tmp.data(), keyword[j])) != 0) {
113 p += strlen(keyword[j]);
114 while(*p && *p != '"')
115 *p++ = 'X';
116 }
117 }
118
119 }
120
121 return 0;
122}
123
124
125void PPPL_AnalyseLog(QStringList &list, QStringList &result) {
126 QString msg;
127 const char *rmsg = "Remote message: ";
128
129 result.clear();
130
131 // setup the analysis database
132 struct {
133 const char *regexp;
134 const char *answer;
135 } hints[] = {
136 {"Receive serial link is not 8-bit clean",
137 I18N_NOOP("You have launched pppd before the remote server " \
138 "was ready to establish a PPP connection.\n"
139 "Please use the terminal-based login to verify") },
140
141 {"Serial line is looped back",
142 I18N_NOOP("You have not started the PPP software on the peer system.") },
143
144 {"AP authentication failed",
145 I18N_NOOP("Check that you supplied the correct username and password.")} ,
146
147 {"is locked by pid",
148 I18N_NOOP("You should not pass 'lock' as an argument to pppd. "
149 "Check /etc/ppp/options and ~/.ppprc") },
150
151 {"CP: timeout sending",
152 I18N_NOOP("The remote system does not seem to answer to\n"
153 "configuration request. Contact your provider.") },
154
155 {"unrecognized option",
156 I18N_NOOP("You have passed an invalid option to pppd. See 'man pppd' "
157 "for a complete list of valid arguments.") },
158
159 // terminator
160 {0,0}
161 };
162
163
164 // scan the log for keywords and try to offer any help
165 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
166 {
167 // look for remote message
168 int pos = (*it).indexOf(rmsg);
169 if (pos != -1)
170 {
171 QString str = (*it);
172 str.remove(0, pos + strlen(rmsg));
173 if(!str.isEmpty()) {
174 msg = i18n("Notice that the remote system has sent the following"
175 " message:\n\"%1\"\nThis may give you a hint why the"
176 " connection has failed.", str);
177 result.append(msg);
178 }
179 }
180
181 // check in the hint database
182 for(uint k = 0; hints[k].regexp != 0; k++) {
183 QRegExp rx(hints[k].regexp);
184 QString l(*it);
185 if(l.contains(rx)) {
186 result.append(i18n(hints[k].answer));
187 break;
188 }
189 }
190 }
191
192 if (result.isEmpty())
193 result.append(i18n("Unable to provide help."));
194}
195
196
197void PPPL_ShowLog() {
198 QStringList sl, result;
199
200 PPPL_MakeLog(sl);
201
202 bool foundConnect = false;
203 bool foundLCP = gpppdata.getPPPDebug();
204 QString lcp = QLatin1String("[LCP");
205 QString conn = QLatin1String("Connect:");
206 QStringList::ConstIterator it = sl.constBegin();
207 for( ; it != sl.constEnd(); it++) {
208 if((*it).indexOf(lcp) >= 0) {
209 foundLCP = true;
210 break;
211 }
212 if((*it).contains(conn))
213 foundConnect = true;
214 }
215 if(foundConnect && !foundLCP) {
216 int result = KMessageBox::warningYesNo(0,
217 i18n("KPPP could not prepare a PPP log. It is very likely "
218 "that pppd was started without the \"debug\" option.\n"
219 "Without this option it is difficult to find out PPP "
220 "problems, so in general the debug option should be used.\n"
221 "Enable debug now, and restart pppd?"), QString(), KGuiItem(i18n("Restart pppd")), KGuiItem(i18n("Do Not Restart")));
222
223 if(result == KMessageBox::Yes) {
224 gpppdata.setPPPDebug(true);
225 KMessageBox::information(0,
226 i18n("The \"debug\" option has been added. You "
227 "should now try to reconnect. If that fails "
228 "again, you will get a PPP log that may help "
229 "you to track down the connection problem."));
230 // return;
231 }
232
233 // return;
234 }
235
236 PPPL_AnalyseLog(sl, result);
237
238 KDialog *dlg = new KDialog();
239 dlg->setButtons(KDialog::Close | KDialog::Ok);
240 dlg->setWindowTitle(i18n("PPP Log"));
241 dlg->setButtonText(KDialog::Ok,i18n("Write to File"));
242
243 KVBox* v = new KVBox(dlg);
244 QTextEdit *edit = new QTextEdit(v);
245 edit->setReadOnly(true);
246 QLabel *label = new QLabel(i18n("kppp's diagnosis (just guessing):"), v);
247 QTextEdit *diagnosis = new QTextEdit(v);
248 diagnosis->setReadOnly(true);
249 edit->setMinimumSize(600, 250);
250 label->setMinimumSize(600, 15);
251 diagnosis->setMinimumSize(600, 60);
252
253 dlg->setMainWidget(v);
254
255 for(int i = 0; i < sl.count(); i++)
256 edit->append(sl.at(i));
257 for(int i = 0; i < result.count(); i++)
258 diagnosis->append(result.at(i));
259
260 if(dlg->exec()) {
261 QDir d = QDir::home();
262 QString s = d.absolutePath() + "/PPP-logfile";
263 int old_umask = umask(0077);
264
265 FILE *f = fopen(QFile::encodeName(s), "w");
266 for(int i = 0; i < sl.count(); i++)
267 fprintf(f, "%s\n", sl.at(i).toLocal8Bit().data());
268 fclose(f);
269 umask(old_umask);
270
271 QString msg = i18n("The PPP log has been saved\nas \"%1\".\n\nIf you want to send a bug report, or have\nproblems connecting to the Internet, please\nattach this file. It will help the maintainers\nto find the bug and to improve KPPP", s);
272 KMessageBox::information(0, msg);
273 }
274 delete dlg;
275}
276