示例#1
0
UT_sint32 GlobSessionPacket::getRemoteRev(void) const
{
	for (size_t i = 0; i < m_pPackets.size(); i++)
	{
		UT_continue_if_fail(m_pPackets[i]);
		SessionPacket* pPacket = m_pPackets[i];
		if (pPacket->getClassType() >= _PCT_FirstChangeRecord && pPacket->getClassType() <= _PCT_LastChangeRecord)
		{
			ChangeRecordSessionPacket* crp = static_cast<ChangeRecordSessionPacket*>( pPacket );
			return crp->getRemoteRev();
		}
	}
	UT_return_val_if_fail(false, 0);
}
示例#2
0
UT_sint32 GlobSessionPacket::getAdjust() const
{
	UT_sint32 iGlobAdjust = 0;
	
	for (size_t i = 0; i < m_pPackets.size(); i++)
	{
		UT_continue_if_fail(m_pPackets[i]);
		SessionPacket* pPacket = m_pPackets[i];
		if (pPacket->getClassType() >= _PCT_FirstChangeRecord && pPacket->getClassType() <= _PCT_LastChangeRecord)
		{
			ChangeRecordSessionPacket* crp = static_cast<ChangeRecordSessionPacket*>( pPacket );
			iGlobAdjust += crp->getAdjust();
		}
	}
	
	return iGlobAdjust;
}
示例#3
0
PT_DocPosition GlobSessionPacket::getPos() const
{
	PT_DocPosition  iGlobPos = 0;

	for (size_t i = 0; i < m_pPackets.size(); i++)
	{
		UT_continue_if_fail(m_pPackets[i]);
		SessionPacket* pPacket = m_pPackets[i];
		if (pPacket->getClassType() >= _PCT_FirstChangeRecord && pPacket->getClassType() <= _PCT_LastChangeRecord)
		{
			ChangeRecordSessionPacket* crp = static_cast<ChangeRecordSessionPacket*>( pPacket );
			if (crp->getPos() > 0) // TODO: check the types, instead of a '0' position check to see if this member contains a real position - MARCM
			{
				if (iGlobPos == 0 || crp->getPos() < iGlobPos)
				{
					iGlobPos = crp->getPos();
				}
			}
			
		}
	}

	return iGlobPos;
}
示例#4
0
void GlobSessionPacket::serialize( Archive& ar )
{
	SessionPacket::serialize( ar );
	
	unsigned int count;
	if (ar.isLoading()) 
	{
		// load packet count
		ar << COMPACT_INT(count);
		m_pPackets.resize( count, NULL );
		
		// load packets
		for (size_t i=0; i<m_pPackets.size(); ++i)
		{
			UT_uint8 classId;
			ar << classId;
			SessionPacket* newPacket = static_cast<SessionPacket*>( Packet::createPacket( (PClassType)classId ) );
			UT_ASSERT(newPacket);		// should this be safer?
			newPacket->setParent( this );
			ar << *newPacket;
			m_pPackets[i] = newPacket;
			// for efficiency reasons, childs of a glob don't serialize their session 
			// and document id's; therefor we set them now manually
			newPacket->setSessionId(getSessionId());
			newPacket->setDocUUID(getDocUUID());
		}
	} 
	else 
	{
		// save packet count
		count = m_pPackets.size();
		ar << COMPACT_INT(count);
		
		// save packets
		for (size_t i=0; i<m_pPackets.size(); ++i) 
		{
			// get and check packet
			SessionPacket* sp = m_pPackets[i];
			UT_ASSERT(sp);				// this really may NEVER fail or addPacket malfunctioned!
			UT_uint8 classId = sp->getClassType();
			ar << classId << *sp;
		}
	}
}
/*!
 * Take a packet, interpret it's contents and apply the implied operations on the document.
 */
bool ABI_Collab_Import::_import(const SessionPacket& packet, UT_sint32 iImportAdjustment, BuddyPtr pCollaborator, bool inGlob)
{
	UT_DEBUGMSG(("ABI_Collab_Import::_import() - packet class type: %d, iImportAdjustment: %d\n", packet.getClassType(), iImportAdjustment));
	UT_return_val_if_fail(pCollaborator, false);

	switch (packet.getClassType())
	{
		case PCT_GlobSessionPacket:
			{
				const GlobSessionPacket* gp = static_cast<const GlobSessionPacket*>(&packet);
				UT_return_val_if_fail(gp->getPackets().size() > 0, false);

				// store the last seen revision from this collaborator (it is immediately used by the export)
				m_remoteRevs[pCollaborator] = gp->getRev();

				for (UT_uint32 j = 0; j < gp->getPackets().size(); j++)
				{
					SessionPacket* pGlobPacket = gp->getPackets()[j];
					if (pGlobPacket)
					{
						bool res = _import(*pGlobPacket, iImportAdjustment, pCollaborator, true); // yay for recursion :)
						if (!res)
						{
							UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
						}
					}
				}

				return true;
			}
		
		case PCT_SignalSessionPacket:
			{
				const SignalSessionPacket* sp = static_cast<const SignalSessionPacket*>(&packet);
				m_pDoc->signalListeners(sp->getSignalType());
				return true;
			}

		case PCT_RevertSessionPacket:
			{
				const RevertSessionPacket* rrp = static_cast<const RevertSessionPacket*>(&packet);
				UT_DEBUGMSG(("Revert packet seen on import for rev: %d\n", rrp->getRev()));

				if (m_iAlreadyRevertedRevs.size() == 0 || m_iAlreadyRevertedRevs.front() != rrp->getRev())
				{
					UT_DEBUGMSG(("Incoming revert for revision %d, which we didn't detect locally (m_iAlreadyRevertedRev: %d)!\n", rrp->getRev(), m_iAlreadyRevertedRevs.front()));
					UT_DEBUGMSG(("DOCUMENT OUT OF SYNC DETECTED!!!!\n"));
					UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
					return false;
				}	

				m_iAlreadyRevertedRevs.pop_front();
				return true;
			}
		case PCT_RevertAckSessionPacket:
			{
				UT_DEBUGMSG(("RevertAck packet seen on import for rev: %d\n", static_cast<const RevertAckSessionPacket*>(&packet)->getRev()));

				// remove this collaborator from our revert ack list; he can play again...
				for (std::vector<std::pair<BuddyPtr, UT_sint32> >::iterator it = m_revertSet.begin(); it != m_revertSet.end(); it++)
				{
					if ((*it).first == pCollaborator)
					{
						UT_DEBUGMSG(("Found collaborator %s on our revert ack list with rev %d! Removing him from the list...\n", (*it).first->getDescription().utf8_str(), (*it).second));
						UT_ASSERT_HARMLESS((*it).second == static_cast<const RevertAckSessionPacket*>(&packet)->getRev());
						m_revertSet.erase(it);
						return true;
					}
				}

				UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
				return false;
			}

		default:
			// silly C++ can't switch on ranges
			if (packet.getClassType() >= _PCT_FirstChangeRecord && packet.getClassType() <= _PCT_LastChangeRecord)
			{
				const ChangeRecordSessionPacket* crp = static_cast<const ChangeRecordSessionPacket*>(&packet);
				UT_DEBUGMSG(("It's safe to import this packet\n"));

				UT_DEBUGMSG(("For CR number %d requested point %d adjustment %d \n",  crp->getRev(), crp->getPos(), iImportAdjustment));

				PT_DocPosition pos = static_cast<PT_DocPosition>(crp->getPos() + iImportAdjustment);
				UT_ASSERT(pos <= getEndOfDoc());

				if (!inGlob)
				{
					// store the last seen revision from this collaborator (it is immediately used by the export)
					// NOTE: if this changerecord is part of a glob, then we don't do this; we'll have
					// already set the revision of the glob itself as the last seen one
					m_remoteRevs[pCollaborator] = crp->getRev();
				}

				// todo: remove these temp vars
				PT_DocPosition iPos2 = 0;

				// process the packet
				switch(crp->getPXType())
				{
					case PX_ChangeRecord::PXT_GlobMarker:
					{
						UT_DEBUGMSG(("Found GLOB marker (ignoring)\n"));
						return true;
					}
					case PX_ChangeRecord::PXT_InsertSpan:
					{
						const InsertSpan_ChangeRecordSessionPacket* icrsp = static_cast<const InsertSpan_ChangeRecordSessionPacket*>( crp );
						UT_UCS4String UCSChars = const_cast<UT_UTF8String&>(icrsp->m_sText).ucs4_str();	// ugly, ucs4_str should be const func!
						PP_AttrProp attrProp;
						attrProp.setAttributes(const_cast<const gchar**>(icrsp->getAtts()));
						attrProp.setProperties(const_cast<const gchar**>(icrsp->getProps()));
						m_pDoc->insertSpan(pos,UCSChars.ucs4_str(),UCSChars.length(), &attrProp);
						break;
					}
					case PX_ChangeRecord::PXT_DeleteSpan:
					{
						iPos2 = pos + crp->getLength();
						PP_AttrProp *p_AttrProp_Before = NULL;
						UT_uint32 icnt = 0;
						m_pDoc->deleteSpan(pos,iPos2,p_AttrProp_Before,icnt,true);
						break;
					}
					case PX_ChangeRecord::PXT_ChangeSpan:
					{
						const Props_ChangeRecordSessionPacket* pcrsp = static_cast<const Props_ChangeRecordSessionPacket*>( crp );
						gchar** szAtts = pcrsp->getAtts();
						gchar** szProps = pcrsp->getProps();
						iPos2 = pos + pcrsp->getLength();
						if((szProps == NULL) && (szAtts == NULL))
						{
							//
							// This happens if we remove all formats
							// we have to handle this seperately
							//
							// Get style of containing block
							//
							pf_Frag_Strux* sdh = NULL;
							m_pDoc->getStruxOfTypeFromPosition(pos,PTX_Block,&sdh);
							if(!sdh)
							{
								UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
								return false;
							}
							PD_Style * pStyle = m_pDoc->getStyleFromSDH(sdh);
							if(!pStyle)
							{
								UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
								return false;
							}
							const gchar * szName =  pStyle->getName();
							const gchar * atts[3] = {PT_STYLE_ATTRIBUTE_NAME,szName,NULL};
							m_pDoc->changeSpanFmt(PTC_SetExactly, pos, iPos2, atts, const_cast<const gchar**>( szProps ) );
						}
						else
						{
							m_pDoc->changeSpanFmt(PTC_SetExactly, pos, iPos2, const_cast<const gchar**>(szAtts), const_cast<const gchar**>( szProps ) );
						}
						break;
					}
					case PX_ChangeRecord::PXT_InsertStrux:
					{
						const ChangeStrux_ChangeRecordSessionPacket* pcrsp = static_cast<const ChangeStrux_ChangeRecordSessionPacket*>( crp );
						PTStruxType pts = pcrsp->m_eStruxType;
						gchar** szAtts = pcrsp->getAtts();
						gchar** szProps = pcrsp->getProps();
						
						if((szProps != NULL) || (szAtts != NULL))
						{
							m_pDoc->insertStrux( pos, pts, const_cast<const gchar**>( szAtts ), const_cast<const gchar**>( szProps ) );
						}
						else
						{
							m_pDoc->insertStrux(pos, pts);
						}
						break;
					}
					case PX_ChangeRecord::PXT_DeleteStrux:
					{
						const DeleteStrux_ChangeRecordSessionPacket* pcrsp = static_cast<const DeleteStrux_ChangeRecordSessionPacket*>( crp );
						PTStruxType pts = pcrsp->m_eStruxType;
						m_pDoc->deleteStrux(pos,pts,true);
						break;
					}
					case PX_ChangeRecord::PXT_ChangeStrux:
					{
						const ChangeStrux_ChangeRecordSessionPacket* pcrsp = static_cast<const ChangeStrux_ChangeRecordSessionPacket*>( crp );
						PTStruxType pts = pcrsp->m_eStruxType;
						gchar** szAtts = pcrsp->getAtts();
						gchar** szProps = pcrsp->getProps();
						UT_return_val_if_fail(szProps != NULL || szAtts != NULL, false);

						UT_DEBUGMSG(("Executing ChangeStrux pos= %d \n",pos));
						m_pDoc->changeStruxFmt(PTC_SetExactly, pos, pos, const_cast<const gchar**>( szAtts ), const_cast<const gchar**>( szProps ), pts);
						
						// TODO: this mask is waaaay to generic
						XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame();
						if (pFrame)
						{
							FV_View* pView = static_cast<FV_View*>(pFrame->getCurrentView());
							if (pView)
								pView->notifyListeners(AV_CHG_TYPING | AV_CHG_FMTCHAR | AV_CHG_FMTBLOCK | AV_CHG_PAGECOUNT | AV_CHG_FMTSTYLE );
						}
						break;
					}
					case PX_ChangeRecord::PXT_InsertObject:
					{
						const Object_ChangeRecordSessionPacket* ocrsp = static_cast<const Object_ChangeRecordSessionPacket*>( crp );
						PTObjectType pto = ocrsp->getObjectType();
						gchar** szAtts = ocrsp->getAtts();
						gchar** szProps = ocrsp->getProps();
						
						if((szProps == NULL) && (szAtts == NULL))
						{
							UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
							return false;
						}
						m_pDoc->insertObject(pos, pto, const_cast<const gchar**>( szAtts ), const_cast<const gchar**>( szProps ) );
						break;
					}
					case PX_ChangeRecord::PXT_DeleteObject:
					{
						iPos2 = pos + 1;
						PP_AttrProp *p_AttrProp_Before = NULL;
						UT_uint32 icnt = 0;
						m_pDoc->deleteSpan(pos, iPos2, p_AttrProp_Before, icnt, true);
						break;
					}
					case PX_ChangeRecord::PXT_ChangeObject:
					{
						const Object_ChangeRecordSessionPacket* ccrsp = static_cast<const Object_ChangeRecordSessionPacket*>( crp );
						//PTObjectType pto = ccrsp->m_eObjectType;
						gchar** szAtts = ccrsp->getAtts();
						gchar** szProps = ccrsp->getProps();
						
						if ((szProps == NULL) && (szAtts == NULL))
						{
							UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
							return false;
						}
						m_pDoc->changeSpanFmt(PTC_SetExactly, pos, pos + 1, const_cast<const gchar**>( szAtts ), const_cast<const gchar**>( szProps ));
						break;
					}
                    case PX_ChangeRecord::PXT_ChangeDocRDF:
                    {
                        // down cast crp to get dcrp
						const RDF_ChangeRecordSessionPacket* dcrp = static_cast<const RDF_ChangeRecordSessionPacket*>( crp );
						gchar** szAtts = dcrp->getAtts();
						gchar** szProps = dcrp->getProps();

						if ((szProps == NULL) && (szAtts == NULL))
						{
							UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
							return false;
						}

                        {
                            // update the local document RDF to remove
                            // szAtts RDF and then add the szProps RDF
                            m_pDoc->getDocumentRDF()->handleCollabEvent( szAtts, szProps );
                        }                        
                        break;
                    }
					case PX_ChangeRecord::PXT_InsertFmtMark:
					{
						const Props_ChangeRecordSessionPacket* pcrsp = static_cast<const Props_ChangeRecordSessionPacket*>( crp );
						gchar** szAtts = pcrsp->getAtts();
						gchar** szProps = pcrsp->getProps();
						
						if((szProps == NULL) && (szAtts == NULL))
						{
							// nothing to do here, please move along
							
							// NOTE: why does this happen anyway? 
							// This happens when for example when sending over tables:
							UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
							return false;
						}
						return m_pDoc->changeSpanFmt(PTC_SetExactly, pos, pos, const_cast<const gchar**>( szAtts ), const_cast<const gchar**>( szProps ));
					}
					case PX_ChangeRecord::PXT_DeleteFmtMark:
					{
						return m_pDoc->deleteFmtMark(pos);
					}
					case PX_ChangeRecord::PXT_ChangeFmtMark:
					{
						const Props_ChangeRecordSessionPacket* pcrsp = static_cast<const Props_ChangeRecordSessionPacket*>( crp );
						gchar** szAtts = pcrsp->getAtts();
						gchar** szProps = pcrsp->getProps();
						
						if ((szProps == NULL) && (szAtts == NULL))
						{
							UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
							return false;
						}
						return m_pDoc->changeSpanFmt(PTC_SetExactly, pos, pos, const_cast<const gchar**>( szAtts ), const_cast<const gchar**>( szProps ));
					}
					case PX_ChangeRecord::PXT_ChangePoint:
					{
						UT_DEBUGMSG(("Change Point CR \n"));
						return m_pDoc->createAndSendCR(pos, crp->getPXType(), true, 0);
					}
					case PX_ChangeRecord::PXT_ListUpdate:
					{
						UT_DEBUGMSG(("ListUpdate CR \n"));
						return m_pDoc->createAndSendCR(pos, crp->getPXType(), true,0);
					}
					case PX_ChangeRecord::PXT_StopList:
					{
						UT_DEBUGMSG(("StopList CR \n"));
						return m_pDoc->createAndSendCR(pos, crp->getPXType(), true,0);
					}
					case PX_ChangeRecord::PXT_UpdateField:
					{
						UT_DEBUGMSG(("UpdateFiled CR \n"));
						return m_pDoc->createAndSendCR(pos, crp->getPXType(), true,0);
					}
					case PX_ChangeRecord::PXT_RemoveList:
					{
						UT_DEBUGMSG(("RemoveList CR \n"));
						return m_pDoc->createAndSendCR(pos, crp->getPXType(), true,0);
					}
					case PX_ChangeRecord::PXT_UpdateLayout:
					{
						UT_DEBUGMSG(("UpdateLayout CR \n"));
						return m_pDoc->createAndSendCR(pos, crp->getPXType(), true,0);
					}
					case PX_ChangeRecord::PXT_CreateDataItem:
					{
						const Data_ChangeRecordSessionPacket* dp = static_cast<const Data_ChangeRecordSessionPacket*>( crp );
						const char * szNameV = g_strdup(dp->getAttribute(PT_DATAITEM_ATTRIBUTE_NAME));
						PD_DataItemHandle pHandle = NULL;
						std::string sToken = dp->m_bTokenSet ? dp->m_sToken : "";
						UT_ByteBuf * pBuf= new UT_ByteBuf();
						UT_DEBUGMSG(("PXT_CreateDataItem: append image buffer @ 0x%p, %lu bytes, sToken %s\n", &dp->m_vecData[0], (long unsigned)dp->m_vecData.size(), sToken.c_str()));
						pBuf->append(reinterpret_cast<const UT_Byte *>( &dp->m_vecData[0] ), dp->m_vecData.size() );
						bool res = m_pDoc->createDataItem(szNameV,false,pBuf,sToken,&pHandle);
						delete pBuf;
						return res;
					}
					case PX_ChangeRecord::PXT_ChangeDocProp:
					{
						UT_DEBUGMSG(("ChangeDocProp CR \n"));
						const Props_ChangeRecordSessionPacket* pcrsp = static_cast<const Props_ChangeRecordSessionPacket*>( crp );
						//
						// Assemble the Attributes for different properties
						//
						const gchar** szAtts = const_cast<const gchar **>(pcrsp->getAtts());
						const gchar** szProps = const_cast<const gchar **>(pcrsp->getProps());
						//
						// Now direct the document to make the changes
						//
						return m_pDoc->changeDocPropeties(szAtts,szProps);
					}
					default:
					{
						UT_DEBUGMSG(("Unimplemented crp->getPXType(): %d\n", crp->getPXType()));
						UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
						break;
					}
				}
				
				return true;
			}
			else
			{
				UT_DEBUGMSG(("ABI_Collab_Import::import called with unhandled packet class type: %d!\n", packet.getClassType()));
				return false;
			}
			break;		
	}

	return false;
}
bool ABI_Collab_Import::import(const SessionPacket& packet, BuddyPtr collaborator)
{
	UT_DEBUGMSG(("ABI_Collab_Import::import()\n"));

	UT_DEBUGMSG(("--------------------------\n"));
	UT_DEBUGMSG(("%s", packet.toStr().c_str()));
	UT_DEBUGMSG(("--------------------------\n"));

	UT_return_val_if_fail(collaborator, false);
	
	// check for collisions to see if we can import this packet at all;
	// NOTE: the position adjustment is calculated in the process, so we don't have to 
	// do that again on import (as calculating it for globs can be quite costly, and
	// we need to do it anyway to properly detect collisions)
	UT_sint32 iImportAdjustment = 0;
	switch (packet.getClassType())
	{
		case PCT_SignalSessionPacket:
			if (_shouldIgnore(collaborator))
				return false;
			// this packet can never cause a collision, let it pass
			break;
		case PCT_RevertSessionPacket:
		case PCT_RevertAckSessionPacket:
			// these packets can never cause collisions, let them pass
			break;
		default:
			if (AbstractChangeRecordSessionPacket::isInstanceOf(packet))
			{
				if (_shouldIgnore(collaborator))
					return false;

				// check for a collision and handle it if it occurred
				const AbstractChangeRecordSessionPacket& acrsp = static_cast<const AbstractChangeRecordSessionPacket&>(packet);
				UT_sint32 iLocalRev = 0;
				bool bCollide = _checkForCollision(acrsp, iLocalRev, iImportAdjustment);
				// make sure we revert all the way upto the first revision in this glob if a collision is detected
				bool continueImport = (bCollide ? _handleCollision(acrsp.getRev(), iLocalRev, collaborator) : true);
				if (!continueImport)
					return false;
			}
			else
			{
				UT_DEBUGMSG(("Unhandled packet class type: %d", packet.getClassType()));
				UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
			}
			break;
	}

	UT_DEBUGMSG(("Collision test succeeded, continuing to import this packet\n"));

	// set the temporary document UUID, so all generated changerecords during
	// import will inherit this UUID


	UT_UTF8String sRealDocname = m_pDoc->getOrigDocUUIDString();
	UT_DEBUGMSG(("Temp. setting document UUID to %s\n", packet.getDocUUID().utf8_str()));
	m_pDoc->setMyUUID(packet.getDocUUID().utf8_str());

	// disable layout/view updates
	UT_GenericVector<AV_View *> vecViews;
	_disableUpdates(vecViews, packet.getClassType() == PCT_GlobSessionPacket);

	// import the changes in the document
	bool bRes = _import(packet, iImportAdjustment, collaborator);	
	// UT_ASSERT_HARMLESS(bRes); // enable this check when stuff like tables don't incorrectly report a failed import due to formatting marks without props/attrs anymore

	// enable layout/view updates
	_enableUpdates(vecViews, packet.getClassType() == PCT_GlobSessionPacket);

	// restore our own document UUID
	m_pDoc->setMyUUID(sRealDocname.utf8_str());
	
	return bRes;
}
示例#7
0
bool AbstractSessionTakeoverPacket::isInstanceOf(const SessionPacket& packet)
{
	return (packet.getClassType() >= _PCT_FirstSessionTakeoverPacket && packet.getClassType() <= _PCT_LastSessionTakeoverPacket);
}
示例#8
0
UT_sint32 GlobSessionPacket::getLength() const
{
//	UT_sint32 iGlobLength = 0;
	
	ChangeRecordSessionPacket* pFirstPacket = NULL;
	ChangeRecordSessionPacket* pLastPacket = NULL;
	
	for (size_t i = 0; i < m_pPackets.size(); i++)
	{
		SessionPacket* pPacket = m_pPackets[i];
		UT_continue_if_fail(pPacket);
		
		switch (pPacket->getClassType())
		{
			/* misc. session packets */
			case PCT_SignalSessionPacket:
				// these packets don't contribute to the length of a glob
				break;
			case PCT_RevertSessionPacket:
			case PCT_RevertAckSessionPacket:
				// these packets should never be in a glob
				UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
				break;
			case PCT_GlobSessionPacket:
				// we don't allow embedded globs in globs
				UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
				break;
			/* changerecord session packets */
			case PCT_ChangeRecordSessionPacket:
			case PCT_Props_ChangeRecordSessionPacket:
			case PCT_InsertSpan_ChangeRecordSessionPacket:
			case PCT_DeleteStrux_ChangeRecordSessionPacket:
			case PCT_Object_ChangeRecordSessionPacket:
			case PCT_RDF_ChangeRecordSessionPacket:
			case PCT_Data_ChangeRecordSessionPacket:
			case PCT_ChangeStrux_ChangeRecordSessionPacket:
				{
					ChangeRecordSessionPacket* crp = static_cast<ChangeRecordSessionPacket*>(pPacket);
					
					UT_ASSERT_HARMLESS(crp->getLength() >= 0);
					
					if (!pFirstPacket ||
						crp->getPos() < pFirstPacket->getPos())
						pFirstPacket = crp;
					if (!pLastPacket || 
						crp->getPos() + crp->getLength() > pLastPacket->getPos() + pLastPacket->getLength())
						pLastPacket = crp;
				}
				break;
			case PCT_Glob_ChangeRecordSessionPacket:
				// this packet doesn't contribute to the length of a glob
				break;
			default:
				UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
				break;
		}
	}
	
	if (!pFirstPacket)
		return 0;
	UT_return_val_if_fail(pLastPacket, 0);
	return pLastPacket->getPos() + pLastPacket->getLength() - pFirstPacket->getPos();
}
示例#9
0
bool AbstractChangeRecordSessionPacket::isInstanceOf(const SessionPacket& packet)
{
	return (packet.getClassType() == PCT_GlobSessionPacket) || 
			(packet.getClassType() >= _PCT_FirstChangeRecord && packet.getClassType() <= _PCT_LastChangeRecord);
}
bool AbiCollabSessionManager::processPacket(AccountHandler& /*handler*/, Packet* packet, BuddyPtr buddy) 
{
	UT_DEBUGMSG(("AbiCollabSessionManager::processPacket()\n"));
	UT_return_val_if_fail(packet, false);
	UT_return_val_if_fail(buddy, false);
	
	// check if this is a simple import-meh-now-packet
	PClassType pct = packet->getClassType();
	if (pct >= _PCT_FirstSessionPacket && pct <= _PCT_LastSessionPacket)
	{
		// lookup session
		SessionPacket* dsp = static_cast<SessionPacket*>( packet );
		const UT_UTF8String& sessionId = dsp->getSessionId();
		AbiCollab* pAbiCollab = getSessionFromSessionId(sessionId);
		if (!pAbiCollab) {
			UT_DEBUGMSG(("Unknown session id: '%s'", sessionId.utf8_str()));
			UT_return_val_if_fail(pAbiCollab, true);
		}
		
		// handle packet!
		pAbiCollab->import(dsp, buddy);
		return true;
	}


	// handle packet
	switch (pct) {
		case PCT_StartSessionEvent:
		{
			StartSessionEvent event;
			event.setBroadcast(true);
			signal(event, buddy);
			return true;
		}
		
		case PCT_JoinSessionEvent:
		{
			JoinSessionEvent* jse = static_cast<JoinSessionEvent*>(packet);
			const UT_UTF8String& joinedSessionId = jse->getSessionId();
			
			// someone who joined this session disconnected, remove him from the collaboration session
			AbiCollab* pSession = getSessionFromSessionId(joinedSessionId);			
			if (pSession)
			{		
				if (isLocallyControlled( pSession->getDocument() ))
				{
					// we should already know this buddy, as we sent should have already added this
					// buddy when responding to his JoinSessionRequest
					// TODO: check this
				}

				// signal all
				JoinSessionEvent event(joinedSessionId);
				signal( event, buddy );				
			}
			else
			{
				// we don't know this session, don't forward the packet
				UT_ASSERT_HARMLESS(UT_NOT_REACHED);			
			}
			return true;
		}
		
		case PCT_DisjoinSessionEvent:
		{
			DisjoinSessionEvent* dse = static_cast<DisjoinSessionEvent*>(packet);
			const UT_UTF8String& disjoinedSessionId = dse->getSessionId();
		
			// someone who joined this session disconnected, remove him from the collaboration session
			AbiCollab* pSession = getSessionFromSessionId(disjoinedSessionId);			
			if (pSession)
			{
				pSession->removeCollaborator(buddy);
				
				// signal all 
				DisjoinSessionEvent event(disjoinedSessionId);
				signal(event, buddy);
			}
			else
			{
				// we don't know this session, don't forward the packet
				UT_ASSERT_HARMLESS(UT_NOT_REACHED);
			}
			return true;
		}
		
		case PCT_CloseSessionEvent:
		{
			CloseSessionEvent* cse = static_cast<CloseSessionEvent*>(packet);
			const UT_UTF8String& destroyedSessionId = cse->getSessionId();
		
			buddy->destroyDocHandle( destroyedSessionId );
			
			// handle the event outselves
			AbiCollab* pSession = getSessionFromSessionId(destroyedSessionId);
			if (pSession)
			{
				if (!isLocallyControlled(pSession->getDocument()))
				{
					std::string docName = pSession->getDocument()->getFilename();
					if (docName == "")
						docName = "Untitled"; // TODO: fetch the title from the frame somehow (which frame?) - MARCM
					
					// the server hosting this session is gone, so let's disconnect as well
					if (!destroySession(pSession))
					{
						UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
					}

					// signal all 
					CloseSessionEvent event( destroyedSessionId );
					signal( event, buddy );

					// inform the user of the disconnect			
					XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame();
					UT_return_val_if_fail(pFrame, true);
					UT_UTF8String msg;
					// TODO: make this localizable
					UT_UTF8String_sprintf(msg, "Document %s is not being shared anymore by buddy %s. You are disconnected from the collaboration session.", docName.c_str(), buddy->getDescription().utf8_str());
					pFrame->showMessageBox(msg.utf8_str(), XAP_Dialog_MessageBox::b_O, XAP_Dialog_MessageBox::a_OK);
				}
				else
				{
					// someone who is not controlling this session sends out messages he closed it!
					// we will not forward this packet
					UT_ASSERT_HARMLESS(UT_NOT_REACHED);
				}
			}
			else
            {
				UT_DEBUGMSG(("Ignoring a CloseSession event for unknown session (%s)\n", destroyedSessionId.utf8_str()));
            }
			return true;
		}
		
		case PCT_AccountAddBuddyRequestEvent:
		{
			// look at this packet; I have a feeling we need to deprecate it - MARCM
			UT_ASSERT_HARMLESS(UT_NOT_IMPLEMENTED);
			return true;
		}
		
		default:
			break;
	}

	return false;
}