00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <iostream>
00025 #include <fstream>
00026
00027 #include <vos/corelibs/vos/vos.hh>
00028 #include "property.hh"
00029 #include <typechain/typechain.hh>
00030
00031 #include <assert.h>
00032
00033
00034
00035 LocalProperty::LocalProperty(MetaObject* superobject)
00036 : MetaObject(superobject), Property(superobject)
00037 {
00038 addMessageHandler<LocalProperty>("property:get-length", this, &LocalProperty::getLengthHandler);
00039 addMessageHandler<LocalProperty>("property:read", this, &LocalProperty::readHandler);
00040 addMessageHandler<LocalProperty>("property:write", this, &LocalProperty::writeHandler);
00041 addMessageHandler<LocalProperty>("property:replace", this, &LocalProperty::replaceHandler);
00042 addMessageHandler<LocalProperty>("property:start-listening", this, &LocalProperty::startListeningHandler);
00043 addMessageHandler<LocalProperty>("property:stop-listening", this, &LocalProperty::stopListeningHandler);
00044 }
00045
00046 LocalProperty::LocalProperty(MetaObject* superobject, const string& d, const string& dt)
00047 : MetaObject(superobject), Property(superobject)
00048 {
00049 raw_data = d;
00050 raw_datatype = dt;
00051 raw_length = raw_data.size();
00052
00053 addMessageHandler<LocalProperty>("property:get-length", this, &LocalProperty::getLengthHandler);
00054 addMessageHandler<LocalProperty>("property:read", this, &LocalProperty::readHandler);
00055 addMessageHandler<LocalProperty>("property:write", this, &LocalProperty::writeHandler);
00056 addMessageHandler<LocalProperty>("property:replace", this, &LocalProperty::replaceHandler);
00057 addMessageHandler<LocalProperty>("property:start-listening", this, &LocalProperty::startListeningHandler);
00058 addMessageHandler<LocalProperty>("property:stop-listening", this, &LocalProperty::stopListeningHandler);
00059 }
00060
00061
00062 LocalProperty::~LocalProperty() {
00063 }
00064
00065
00066 void LocalProperty::setSecurityCallback(PropertySecurityInitializer* newcallback)
00067 {
00068 if(RefCounted* r = dynamic_cast<RefCounted*>(securitycallback)){
00069 r->release();
00070 }
00071 if(RefCounted* r = dynamic_cast<RefCounted*>(newcallback)){
00072 r->acquire();
00073 }
00074 securitycallback = newcallback;
00075 }
00076
00077
00078
00079 void LocalProperty::write(Vobject& initiator, int start, const string& newdata)
00080 {
00081 string oldvalue;
00082 string newvalue;
00083 Property::read(oldvalue);
00084 Property::write(start, newdata);
00085 Property::read(newvalue);
00086
00087 vRef<PropertyEvent> event = new PropertyEvent(PropertyEvent::PropertyWrite,
00088 initiator, *this,
00089 start, newdata.size(),
00090 newvalue,
00091 getDataType(),
00092 oldvalue,
00093 getDataType(),
00094 false);
00095
00096 for(PropertyListenerMap::iterator i = propertyListeners.begin(); i != propertyListeners.end(); i++) {
00097 (*i).second->notifyPropertyChange(*event);
00098 }
00099 }
00100
00101 void LocalProperty::write(int start, const string& newdata)
00102 {
00103 write(*this, start, newdata);
00104 }
00105
00106
00107 void LocalProperty::replace(Vobject& initiator, const string& newdata,
00108 const string& newtype)
00109 {
00110 string oldvalue;
00111 string olddatatype;
00112 Property::read(oldvalue);
00113 olddatatype = Property::getDataType();
00114
00115 Property::replace(newdata, newtype);
00116
00117 vRef<PropertyEvent> event = new PropertyEvent(PropertyEvent::PropertyWrite,
00118 initiator, *this,
00119 newdata,
00120 newtype,
00121 oldvalue,
00122 olddatatype,
00123 false);
00124
00125
00126 for(PropertyListenerMap::iterator i = propertyListeners.begin(); i != propertyListeners.end(); i++) {
00127 (*i).second->notifyPropertyChange(*event);
00128 }
00129 }
00130
00131
00132 void LocalProperty::replace(const string& newdata, const string& newtype)
00133 {
00134 replace(*this, newdata, newtype);
00135 }
00136
00137 void LocalProperty::getLengthHandler(Message* m)
00138 {
00139 vRef<Message> reply = new Message();
00140 LocalVobject::initReply(this, &reply, m, "property:length-update");
00141
00142 vRef<Vobject> from = Vobject::findObjectFromRoot(m->getFrom());
00143
00144
00145 vRef<PropertyEvent> event = new PropertyEvent(PropertyEvent::PropertyRead,
00146 *from, *this,
00147 read(),
00148 getDataType(),
00149 true);
00150 string message;
00151 if(validatePropertyAccess(*event, message)) {
00152 char sz[16];
00153 sprintf(sz, "%i", getRawLength());
00154 reply->insertField(-1, "len", string(sz));
00155 } else {
00156 reply->insertField(-1, "error", message);
00157 }
00158
00159 from->sendMessage(&reply);
00160 }
00161
00162 void LocalProperty::readHandler(Message* m)
00163 {
00164 vRef<Message> reply = new Message();
00165 vRef<Vobject> from = Vobject::findObjectFromRoot(m->getFrom());
00166
00167 int off=atoi(m->getField("start").value.c_str());
00168 int len=atoi(m->getField("length").value.c_str());
00169 if(off == 0 && len == -1) LocalVobject::initReply(this, &reply, m, "property:replace-update");
00170 else LocalVobject::initReply(this, &reply, m, "property:update");
00171
00172
00173 vRef<PropertyEvent> event = new PropertyEvent(PropertyEvent::PropertyRead,
00174 *from, *this,
00175 off, len,
00176 read(),
00177 getDataType(),
00178 true);
00179 string message;
00180
00181 if(validatePropertyAccess(*event, message)) {
00182 string dat;
00183 readRaw(dat, off, len);
00184 reply->insertField(-1, "start", m->getField("start").value);
00185 reply->insertField(-1, "data", dat, true);
00186 reply->insertField(-1, "datatype", getRawDataType(), true);
00187 } else {
00188 reply->insertField(-1, "error", message);
00189 }
00190
00191 from->sendMessage(&reply);
00192 }
00193
00194 void LocalProperty::writeHandler(Message* m)
00195 {
00196 vRef<Message> reply = new Message();
00197 LocalVobject::initReply(this, &reply, m, "property:update");
00198 vRef<Vobject> from = Vobject::findObjectFromRoot(m->getFrom());
00199 try {
00200 int off=atoi(m->getField("start").value.c_str());
00201 string f = m->getField("data").value;
00202
00203 string precommit;
00204 readRaw(precommit);
00205 precommit.replace(off, f.size(), f);
00206
00207 vRef<PropertyEvent> event = new PropertyEvent(
00208 PropertyEvent::PropertyWrite,
00209 *from, *this,
00210 off, f.size(),
00211 precommit, getDataType(),
00212 read(), getDataType(),
00213 true);
00214 string message;
00215 if(validatePropertyAccess(*event, message)) {
00216 vRef<Site> site = from->getSite();
00217 PropertyListenerSiteWrapper plsw(&site);
00218 PropertyListenerMap::iterator plsit =
00219 propertyListeners.find(&plsw);
00220 PropertyListener* plsw2 = 0;
00221 if(plsit != propertyListeners.end()) plsw2 = (*plsit).second;
00222 if(plsw2) propertyListeners.erase(plsw2);
00223 write(*from, off, f);
00224 if(plsw2) propertyListeners[plsw2] = plsw2;
00225 string d;
00226 readRaw(d, off, f.size());
00227 reply->insertField(-1, "data", d, true);
00228 } else {
00229 reply->insertField(-1, "error", message);
00230 }
00231 } catch(Message::NoSuchFieldError) {
00232 reply->insertField(-1, "error", "no data field");
00233 }
00234
00235 from->sendMessage(&reply);
00236 }
00237
00238 void LocalProperty::replaceHandler(Message* m)
00239 {
00240 vRef<Message> reply = new Message();
00241 if(m->getNonce() != "") LocalVobject::initReply(this, &reply, m, "property:replace-update");
00242
00243 vRef<Vobject> from = Vobject::findObjectFromRoot(m->getFrom());
00244 try {
00245 string d = m->getField("data").value;
00246 string t = m->getField("datatype").value;
00247
00248 vRef<PropertyEvent> event = new PropertyEvent(
00249 PropertyEvent::PropertyReplace,
00250 *from, *this,
00251 d, t,
00252 read(), getDataType(),
00253 true);
00254 string message;
00255
00256 if(validatePropertyAccess(*event, message)) {
00257 vRef<Site> site = from->getSite();
00258 PropertyListenerSiteWrapper plsw(&site);
00259 PropertyListenerMap::iterator plsit =
00260 propertyListeners.find(&plsw);
00261 PropertyListener* plsw2 = 0;
00262 if(plsit != propertyListeners.end()) plsw2 = (*plsit).second;
00263 if(plsw2) propertyListeners.erase(plsw2);
00264 replace(*from, d, t);
00265 if(plsw2) propertyListeners[plsw2] = plsw2;
00266 string nd;
00267 readRaw(nd);
00268 if(m->getNonce() != "") {
00269 reply->insertField(-1, "data", d, true);
00270 reply->insertField(-1, "datatype", getRawDataType(), true);
00271 }
00272 } else {
00273 if(m->getNonce() != "") reply->insertField(-1, "error", message);
00274 LOG("property", 2, "permission denied to " << m->getFrom() << " to write to " << getURL().getString() << " (" << message << ")");
00275 }
00276 } catch(Message::NoSuchFieldError) {
00277 if(m->getNonce() != "") reply->insertField(-1, "error", "no data field");
00278 }
00279
00280 if(m->getNonce() != "") from->sendMessage(&reply);
00281 }
00282
00283 void LocalProperty::startListeningHandler(Message* m)
00284 {
00285 try {
00286 for(int i = 0; i < m->getNumFields(); i++) {
00287 if(m->getField(i).key == "listen"
00288 && m->getField(i).value == "property") {
00289 vRef<Site> st = m->getSourceSite();
00290
00291 vRef<PropertyEvent> event =
00292 new PropertyEvent(PropertyEvent::PropertyRead,
00293 *st, *this,
00294 read(),
00295 getDataType(),
00296 true);
00297 string message;
00298 if(validatePropertyAccess(*event, message)) {
00299 vRef<Message> reply = new Message();
00300 LocalVobject::initReply(this, &reply, m, "property:start-listening-reply");
00301 reply->setNonce(m->getNonce() + string("-1"));
00302 reply->insertField(-1, "listen", "property");
00303 vRef<Vobject> from = findObject(m->getFrom());
00304 from->sendMessage(&reply);
00305
00306 PropertyListenerSiteWrapper* pl = new PropertyListenerSiteWrapper(&st, m->getNonce());
00307 LOG("Property", 5, "allocated plsw at " << pl);
00308
00309 addPropertyListener(pl);
00310 st->addExciseListener(this);
00311 } else {
00312 }
00313 break;
00314 }
00315 }
00316 } catch(Message::NoSuchFieldError) {
00317 } catch(NoSuchObjectError) { }
00318 }
00319
00320 void LocalProperty::stopListeningHandler(Message* m)
00321 {
00322 try {
00323 if(m->getField("listen").value == "property") {
00324 PropertyListenerMap::iterator i;
00325 vRef<Site> st = m->getSourceSite();
00326 PropertyListenerSiteWrapper plsw(&st);
00327 i = propertyListeners.find(&plsw);
00328 if(i != propertyListeners.end()) {
00329 removePropertyListener((*i).second);
00330 st->removeExciseListener(this);
00331 LOG("Property", 4, "aha did a stop-listening here! " << (*i).second);
00332 delete (*i).second;
00333 }
00334 }
00335 } catch(Message::NoSuchFieldError) { }
00336 }
00337
00338 MetaObject* LocalProperty::new_LocalProperty(MetaObject* superobject, const string& type)
00339 {
00340 return new LocalProperty(superobject);
00341 }
00342
00343 void LocalProperty::addPropertyListener(PropertyListener* pl, bool refresh)
00344 {
00345 Property::addPropertyListener(pl, refresh);
00346 if(refresh) {
00347 string d;
00348 read(d);
00349 vRef<PropertyEvent> event =
00350 new PropertyEvent(PropertyEvent::PropertyReplace,
00351 *this, *this, d, getDataType(), false);
00352
00353 pl->notifyPropertyChange(*event);
00354 }
00355 }
00356
00357 void LocalProperty::initializeSecurity(Vobject& requester)
00358 {
00359 LOG("LocalProperty", 4, "initializing security on this property with requester "
00360 << requester.getURL().getString());
00361 securitycallback->initializePropertyAccessControl(this, requester);
00362 }
00363
00364
00365 void LocalProperty::insertPropertyAccessControl(int pos, PropertyAccessControl* ac)
00366 {
00367 if(pos < 0) pos += accesscontrols.size() + 1;
00368 accesscontrols.insert(accesscontrols.begin() + pos, ac);
00369 }
00370
00371 void LocalProperty::insertPropertyAccessControl(int pos, const string& policyname)
00372 {
00373 if(pos < 0) pos += accesscontrols.size() + 1;
00374
00375 PropertyAccessControl* ac = PropertyAccessControl::getPolicy(policyname, this);
00376 if(ac) accesscontrols.insert(accesscontrols.begin() + pos, ac);
00377 }
00378
00379 void LocalProperty::removePropertyAccessControl(int pos)
00380 {
00381 if(pos < 0) pos += accesscontrols.size() + 1;
00382 accesscontrols.erase(accesscontrols.begin() + pos);
00383 }
00384
00385 void LocalProperty::removePropertyAccessControl(PropertyAccessControl* ac)
00386 {
00387 for(unsigned int i = 0; i < accesscontrols.size(); i++) {
00388 if(accesscontrols[i] == ac) {
00389 accesscontrols.erase(accesscontrols.begin() + i);
00390 i--;
00391 }
00392 }
00393 }
00394
00395 void LocalProperty::removePropertyAccessControl(const string& policyname)
00396 {
00397 for(unsigned int i = 0; i < accesscontrols.size(); i++) {
00398 if(accesscontrols[i]->getPolicyName() == policyname) {
00399 accesscontrols.erase(accesscontrols.begin() + i);
00400 i--;
00401 }
00402 }
00403 }
00404
00405 const deque<PropertyAccessControl*>& LocalProperty::getPropertyAccessControls()
00406 {
00407 return accesscontrols;
00408 }
00409
00410 bool LocalProperty::validatePropertyAccess(PropertyEvent& e, string& message)
00411 {
00412 if(accesscontrols.size() == 0) {
00413 message = "Error in access policy list. Permission denied by default.";
00414 LOG("localproperty", 1, "Access policy list for "
00415 << e.getProperty()->getURL().getString() << " is empty!");
00416 return false;
00417 }
00418
00419 for(unsigned int i = 0; i < accesscontrols.size(); i++) {
00420 if(! accesscontrols[i]) {
00421 message = "Error in access policy list. Permission denied by default.";
00422 LOG("localvobject", 1, "Access policy list "
00423 << e.getProperty()->getURL().getString() << " contains an invalid (null) policy!");
00424 return false;
00425 }
00426 switch(e.getEvent()) {
00427 case PropertyEvent::PropertyWrite:
00428 case PropertyEvent::PropertyReplace:
00429 if(! accesscontrols[i]->checkChangePermission(e, message)) return false;
00430 break;
00431 case PropertyEvent::PropertyRead:
00432 if(! accesscontrols[i]->checkReadPermission(e, message)) return false;
00433 break;
00434 default:
00435 message = "Supplied validateAccess with an unsupported event type!";
00436 LOG("localvobject", 1, "Supplied validateAccess with an unsupported event type " << e.getEvent());
00437 return false;
00438 }
00439 }
00440 return true;
00441 }