00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <cxxtls/file.h>
00030 #include <cxxtls/ftp.h>
00031 #include <cxxtls/cursorwindow.h>
00032 #include <cxxtls/strtool.h>
00033 #include <iostream>
00034 #include <stdlib.h>
00035 #include <portable_io.h>
00036 #include <fstream>
00037 #include <portable_strstream.h>
00038
00039 using namespace std;
00040 using namespace cxxtls;
00041
00042
00043
00049
00050
00051 class DisplayList
00052
00058
00059 {
00060 public:
00061
00062 typedef list<string> rep_t;
00063 typedef rep_t::iterator iterator;
00064
00065 private:
00066
00067 rep_t rep_;
00068 size_t size_;
00069
00070 public:
00071
00072 DisplayList()
00073 : size_(0)
00074 {
00075 }
00076
00077 iterator begin() { return rep_.begin(); }
00078 iterator end() { return rep_.end(); }
00079
00080 DisplayList &operator += (string const &s)
00081 {
00082 ++size_;
00083
00084 rep_.push_back(s);
00085
00086 return *this;
00087 }
00088
00089 size_t size() const { return size_; }
00090
00091
00092 };
00093
00094
00095 class ResizeHandler
00096
00104
00105 : public CursorWindow::resize_handler
00106 {
00107
00108 public:
00109
00110 typedef DisplayList::iterator iterator;
00111 typedef CursorWindow::row_col row_col;
00112
00113 private:
00114
00115 DisplayList * list_;
00116 iterator top_;
00117 FileName title_;
00118 int page_offset_;
00119 int lines_on_page_;
00120
00121 public:
00122
00123 ResizeHandler(DisplayList *l, FileName title)
00124 : list_(l),
00125 top_(l->begin()),
00126 title_(title),
00127 page_offset_(0)
00128 {
00129 }
00130
00131 void operator() (CursorWindow* w)
00132 {
00133
00134 w->set_curpos(1,0);
00135
00136 w->set_text_attribute(CursorWindow::normal);
00137
00138 iterator scan = top_;
00139
00140 int rows = w->size().row_ - 1;
00141
00142 lines_on_page_ = 0;
00143
00144 for(int i = 1; i < rows && scan != list_->end(); ++i, ++scan)
00145 {
00146 ++lines_on_page_;
00147
00148 if(i == page_offset_ + 1)
00149 {
00150 w->set_text_attribute(CursorWindow::reversed);
00151
00152 w->write(*scan);
00153 w->fill_to_eol();
00154
00155 w->set_text_attribute(CursorWindow::normal);
00156 }
00157 else
00158 {
00159 w->write(*scan);
00160 w->fill_to_eol();
00161 }
00162 }
00163
00164 w->fill_to_eos('_');
00165
00166 w->set_curpos(0,0);
00167
00168 w->set_text_attribute(CursorWindow::reversed);
00169
00170 w->write(title_);
00171 w->fill_to_eol();
00172
00173 char buffer[40];
00174
00175 sprintf(buffer, "%lu", (unsigned long)(list_->size()) );
00176
00177 int l = strlen(buffer);
00178
00179 w->set_curpos(0, w->size().col_ - l);
00180 w->write(buffer);
00181
00182
00183 if(page_offset_ >= lines_on_page_)
00184 {
00185
00186
00187
00188
00189
00190 if(lines_on_page_ == 0)
00191 page_offset_ = 0;
00192 else
00193 {
00194
00195 page_offset_ = lines_on_page_-1;
00196
00197 int i;
00198
00199 for(i=0, scan = top_; i < lines_on_page_; ++i, ++scan)
00200 {
00201 if(i == page_offset_)
00202 break;
00203 }
00204
00205 w->set_curpos(1 + page_offset_, 0);
00206 w->set_text_attribute(CursorWindow::reversed);
00207 w->write(*scan);
00208 w->fill_to_eol();
00209
00210
00211 }
00212 }
00213
00214 }
00215
00216 void pageup(CursorWindow* w)
00217 {
00218
00219 int pagesize = w->size().row_;
00220
00221 pagesize -= 2;
00222
00223 while(pagesize && top_ != list_->begin())
00224 {
00225 --pagesize;
00226 --top_;
00227 }
00228
00229 page_offset_ = 0;
00230
00231 (*this)(w);
00232
00233
00234 }
00235
00236 void pagedown(CursorWindow* w)
00237 {
00238
00239 int pagesize = w->size().row_;
00240
00241 pagesize -= 2;
00242
00243 iterator save = top_;
00244
00245 while(pagesize && top_ != list_->end())
00246 {
00247 --pagesize;
00248
00249 save = top_;
00250
00251 ++top_;
00252 }
00253
00254 if(top_ == list_->end())
00255
00256 top_ = save;
00257
00258 page_offset_ = 0;
00259
00260 (*this)(w);
00261
00262
00263 }
00264
00265 void lineup(CursorWindow*w)
00266 {
00267 if(page_offset_ == 0)
00268 {
00269 if(top_ == list_->begin())
00270 return;
00271
00272 --top_;
00273
00274 (*this)(w);
00275 }
00276 else
00277 {
00278 if(lines_on_page_ == 0)
00279 return;
00280
00281 int offset = 0;
00282
00283 iterator ip = top_;
00284
00285 while(offset != page_offset_)
00286 {
00287 ++offset;
00288 ++ip;
00289 }
00290
00291
00292
00293
00294 w->set_text_attribute(CursorWindow::normal);
00295 w->set_curpos(1 + page_offset_, 0);
00296 w->write(*ip);
00297 w->fill_to_eol();
00298
00299
00300
00301
00302
00303 --ip;
00304 --page_offset_;
00305
00306 w->set_text_attribute(CursorWindow::reversed);
00307 w->set_curpos(1 + page_offset_, 0);
00308 w->write(*ip);
00309 w->fill_to_eol();
00310
00311 w->set_curpos(1 + page_offset_, 0);
00312
00313
00314 }
00315
00316 }
00317
00318 void linedown(CursorWindow*w)
00319 {
00320 if(lines_on_page_ < 2)
00321 return;
00322
00323 if(page_offset_ >= lines_on_page_ -1)
00324 {
00325 iterator save = top_;
00326
00327 if(top_ != list_->end())
00328 ++top_;
00329
00330 if(top_ == list_->end())
00331 top_ = save;
00332
00333 (*this)(w);
00334
00335 }
00336 else
00337 {
00338 int offset = 0;
00339
00340 iterator ip = top_;
00341
00342 while(offset != page_offset_)
00343 {
00344 ++offset;
00345 ++ip;
00346 }
00347
00348
00349
00350
00351 w->set_text_attribute(CursorWindow::normal);
00352 w->set_curpos(1 + page_offset_, 0);
00353
00354 w->write(*ip);
00355 w->fill_to_eol();
00356
00357
00358
00359 ++page_offset_;
00360 ++ip;
00361
00362 w->set_text_attribute(CursorWindow::reversed);
00363 w->set_curpos(1 + page_offset_, 0);
00364 w->write(*ip);
00365 w->fill_to_eol();
00366
00367
00368
00369 w->set_curpos(1 + page_offset_, 0);
00370
00371 }
00372
00373 }
00374
00375 };
00376
00377 static char binary_char='#';
00378
00379 static void readfile(FileName const &f, DisplayList &l)
00380 {
00381 if(!f.exists())
00382 {
00383 cerr << "Error: expected existing file or directory" << endl;
00384 exit(1);
00385 }
00386
00387 fstream file;
00388
00389 file.open(f.c_str(), ios::in);
00390
00391 if(file.fail())
00392 {
00393 cerr << "error: couldn't open " << f << endl;
00394 exit(1);
00395 }
00396
00397 istreambuf_iterator<char> nc(file);
00398 istreambuf_iterator<char> lc;
00399
00400 string line;
00401
00402 while(nc != lc)
00403 {
00404 char c = *nc++;
00405
00406
00407 if(c == '\n')
00408 {
00409 l += StrTool::expand_tabs(line,0,binary_char);
00410 line.resize(0);
00411 }
00412 else
00413 line += c;
00414
00415 }
00416
00417 if(line.size())
00418 l += StrTool::expand_tabs(line,0,binary_char);
00419
00420
00421 file.close();
00422 }
00423
00424
00425 int main(int argc, char **argv)
00426 {
00427 if(argc < 2)
00428 {
00429 cerr << "Error: expected pathname" << endl;
00430 exit(1);
00431 }
00432
00433 FileName f(argv[1]);
00434
00435
00436 DisplayList l;
00437
00438
00439 if(f[0] == 'f' &&
00440 f[1] == 't' &&
00441 f[2] == 'p' &&
00442 f[3] == ':' &&
00443 f[4] == '/' &&
00444 f[5] == '/'
00445 )
00446 {
00447
00448
00449 string rest(f.begin()+6, f.end());
00450
00451 size_t slash = rest.find_first_of('/',0);
00452
00453 if(slash >= rest.size())
00454 {
00455 cerr << "badly formatted ftp file name: " << f << endl;
00456 cerr << endl;
00457 cerr << "expected ftp://user:pass@host/directory/file" << endl;
00458 exit(1);
00459 }
00460
00461 string path(rest.begin() + slash, rest.end());
00462
00463 string user_password_host(rest.begin(), rest.begin() + slash);
00464
00465 size_t colon = user_password_host.find_first_of(':');
00466
00467 if(colon >= user_password_host.size())
00468 {
00469 cerr << "badly formatted ftp file name: " << f << endl;
00470 cerr << endl;
00471 cerr << "expected ftp://user:pass@host/directory/file" << endl;
00472 exit(1);
00473 }
00474
00475 string user(user_password_host.begin(), user_password_host.begin() + colon);
00476
00477 string password_host(user_password_host.begin() + colon + 1,
00478 user_password_host.end()
00479 );
00480
00481 size_t at = password_host.find_first_of('@');
00482
00483 if(at >= password_host.size())
00484 {
00485 cerr << "badly formatted ftp file name: " << f << endl;
00486 cerr << endl;
00487 cerr << "expected ftp://user:pass@host/directory/file" << endl;
00488 exit(1);
00489 }
00490
00491 string password(password_host.begin(),
00492 password_host.begin() + at
00493 );
00494
00495 string host(password_host.begin() + at + 1,
00496 password_host.end()
00497 );
00498
00499
00500 std::list<FTP::FileInfo> stats;
00501
00502 std::list<FTP::FileInfo> target_status;
00503
00504 bool force_directory_status=false;
00505
00506 if(FTP::stat_matching(host,
00507 user,
00508 password,
00509 path,
00510 &target_status
00511 )
00512 )
00513 {
00514 if(path.size() &&
00515 path[path.size()-1] == '/'
00516 )
00517 {
00518 force_directory_status=true;
00519
00520 }
00521 else
00522 {
00523 cerr << "No such remote file as " << f << endl;
00524 exit(1);
00525 }
00526
00527 }
00528
00529 if(force_directory_status ||
00530 target_status.front().status_.mode.is_dir()
00531 )
00532 {
00533 FileName dirSearchPattern(path); dirSearchPattern.convertToDirectorySearchPattern();
00534
00535 FTP::stat_matching(host, user, password, dirSearchPattern, &stats);
00536
00537 std::list<FTP::FileInfo>::iterator first=stats.begin(),
00538 last =stats.end();
00539
00540 while(first != last)
00541 {
00542 FTP::FileInfo &info = *first++;
00543
00544 FileStatus& status = info.status_;
00545
00546 string line;
00547
00548 line += status.mode;
00549 line += " ";
00550 line += status.time;
00551 line += " ";
00552
00553 char buffer[40];
00554
00555 sprintf(buffer, "%12lu", (unsigned long)status.size);
00556
00557 line += buffer;
00558 line += " ";
00559 line += info.name_;
00560
00561 l += line;
00562
00563 }
00564 }
00565 else
00566 {
00567
00568
00569 FileName tmp = FileName::mktemp();
00570
00571 if(FTP::get(host, user, password, path, tmp))
00572 {
00573 cerr << "Error couldn't get remote file " << f << endl;
00574 exit(1);
00575 }
00576
00577 readfile(tmp, l);
00578
00579 tmp.remove();
00580
00581 }
00582
00583
00584
00585 }
00586 else
00587 if(f.is_dir())
00588 {
00589 FileName::sorted_names_t lf;
00590
00591 FileName dirSearchPattern(f); dirSearchPattern.convertToDirectorySearchPattern();
00592
00593 f.find_matching(dirSearchPattern, &lf);
00594
00595
00596 f.convert_to_absolute_path();
00597
00598 FileName::sorted_names_t::iterator f = lf.begin();
00599 FileName::sorted_names_t::iterator e = lf.end();
00600
00601 while(f != e)
00602 {
00603 FileStatus status;
00604
00605 f->file_stat(&status);
00606
00607 string line;
00608
00609 line += status.mode;
00610 line += " ";
00611 line += status.time;
00612 line += " ";
00613
00614 char buffer[40];
00615
00616 sprintf(buffer, "%12lu", (unsigned long)status.size);
00617
00618 line += buffer;
00619 line += " ";
00620 line += *f;
00621
00622 l += line;
00623
00624 ++f;
00625
00626 }
00627
00628
00629 }
00630 else
00631 {
00632
00633 readfile(f, l);
00634
00635 }
00636
00637 CursorWindow w;
00638
00639 w.open();
00640
00641 ResizeHandler r(&l, f);
00642
00643 r(&w);
00644
00645 w.set_resize_handler(&r);
00646
00647 for(;;)
00648 {
00649 CursorWindow::input_event e = w.read_input();
00650
00651 if(e.type_ == CursorWindow::input_event::DataKey)
00652 {
00653 switch(e.value_)
00654 {
00655 case 'q':
00656 case 'Q':
00657 case 0x1b:
00658 return 0;
00659 }
00660 }
00661 else
00662 {
00663 switch(e.value_)
00664 {
00665 case CursorWindow::key_prior:
00666 r.pageup(&w);
00667 break;
00668
00669 case CursorWindow::key_next:
00670 r.pagedown(&w);
00671 break;
00672
00673 case CursorWindow::key_up:
00674 r.lineup(&w);
00675 break;
00676
00677 case CursorWindow::key_down:
00678 r.linedown(&w);
00679 break;
00680
00681
00682
00683 }
00684
00685 }
00686
00687
00688 }
00689
00690
00691
00692
00693 }